You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@JsonUnwrapped时Jackson能否同时支持包装与解包两种JSON输入格式

解决方案

方案1:轻量注解兼容(推荐)

无需编写复杂逻辑,仅需在外层类增加一个专属setter即可同时兼容两种格式,原理是利用@JsonUnwrapped处理解包格式的平级字段,额外新增的@JsonProperty方法处理包装格式的嵌套对象:

// 外层类示例
public class Parent {
    // 原有注解保留,负责接收解包格式的nested1、nested2字段
    @JsonUnwrapped
    private DataObject dataObject;

    // 新增setter,仅在反序列化时接收包装格式的dataObject嵌套对象
    @JsonProperty(value = "dataObject", access = JsonProperty.Access.WRITE_ONLY)
    public void setWrappedDataObject(DataObject dataObject) {
        this.dataObject = dataObject;
    }

    // 原有getter、其他属性和方法保持不变
    public DataObject getDataObject() {
        return dataObject;
    }
}

DataObject类无需修改,补充无参构造即可正常使用:

@Getter
@NoArgsConstructor // 确保有无参构造供Jackson反序列化
public class DataObject {
    private String nested1;
    private String nested2;
}

方案2:自定义反序列化器(适合复杂兼容场景)

如果后续还有其他字段的兼容需求,可以通过自定义反序列化器手动判断JSON结构,灵活处理两种格式:

  1. 首先编写自定义反序列化类:
public class ParentDeserializer extends StdDeserializer<Parent> {
    public ParentDeserializer() {
        super(Parent.class);
    }

    @Override
    public Parent deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode rootNode = p.getCodec().readTree(p);
        ObjectMapper mapper = (ObjectMapper) p.getCodec();
        Parent parent = new Parent();
        DataObject dataObject;

        // 识别当前JSON是包装格式还是解包格式
        if (rootNode.has("dataObject")) {
            dataObject = mapper.treeToValue(rootNode.get("dataObject"), DataObject.class);
        } else {
            dataObject = mapper.treeToValue(rootNode, DataObject.class);
        }
        parent.setDataObject(dataObject);
        
        // 外层类其他属性的赋值逻辑可在这里补充
        // 示例:parent.setOtherField(rootNode.get("otherField").asText());
        return parent;
    }
}
  1. 给外层类绑定反序列化器:
@JsonDeserialize(using = ParentDeserializer.class)
public class Parent {
    private DataObject dataObject;
    // 其他属性、getter、setter
}
注意事项
  • 方案1依赖Jackson 2.6及以上版本,JsonProperty.Access.WRITE_ONLY为该版本新增特性
  • 两种方案都要求DataObject类提供无参构造函数,否则Jackson会抛出反序列化异常
  • 默认序列化输出为解包格式,如果需要输出包装格式,仅需去掉外层类的@JsonUnwrapped注解即可

内容的提问来源于stack exchange,提问作者Peter Kronenberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 11:45:01