Jackson反序列化:无需@JsonProperty映射嵌套JSON至POJO
问题:Jackson嵌套字段映射的替代注解方案
给定如下JSON数据:
{ "params": [ { "key": "path", "options": { "string": { "prefix": "test_pref" } }, "default": { "url": "" } } ]}
对应的POJO类定义如下,目前通过@JsonProperty指定完整JSON路径的方式,将嵌套字段(如options.string.prefix)映射到Params类的prefix属性。请问有没有其他Jackson注解可以替代@JsonProperty实现这个需求?
@Data @Accessors(chain = true) public class Data { private List<Params> params; } @Data @Accessors(chain = true) public class Params { private String key; @JsonProperty("options.string.prefix") private String prefix; @JsonProperty("default.url") private String url; }
可行的替代方案
1. 使用@JsonSetter注解
@JsonSetter专门用于反序列化阶段的字段映射,功能上可替代@JsonProperty的反序列化作用(若无需兼顾序列化),用法完全一致:
@Data @Accessors(chain = true) public class Params { private String key; @JsonSetter("options.string.prefix") private String prefix; @JsonSetter("default.url") private String url; }
2. 结合@JsonCreator与构造函数参数注解
通过构造函数注入的方式,在参数上用@JsonProperty指定路径,实现嵌套字段映射,适合强调不可变性的场景:
@Data @Accessors(chain = true) public class Params { private String key; private String prefix; private String url; @JsonCreator public Params( @JsonProperty("key") String key, @JsonProperty("options.string.prefix") String prefix, @JsonProperty("default.url") String url ) { this.key = key; this.prefix = prefix; this.url = url; } }
3. 使用@JsonPath注解(需额外依赖)
引入jackson-module-json-path模块后,可通过@JsonPath用JSONPath表达式指定映射路径,写法更灵活:
// 需先引入依赖:com.fasterxml.jackson.module:jackson-module-json-path @Data @Accessors(chain = true) public class Params { private String key; @JsonPath("$.options.string.prefix") private String prefix; @JsonPath("$.default.url") private String url; }
4. 拆分嵌套对象(额外类定义)
虽然不算直接替代注解,但可通过拆分嵌套内部类,配合@JsonProperty映射完整对象,再通过自定义getter/setter平展属性,适合需要复用嵌套结构的场景:
@Data @Accessors(chain = true) public class Params { private String key; @JsonProperty("options") private Options options; @JsonProperty("default") private DefaultUrl defaultUrl; public String getPrefix() { return options != null ? options.getString().getPrefix() : null; } public void setPrefix(String prefix) { if (options == null) options = new Options(); if (options.getString() == null) options.setString(new StringOpts()); options.getString().setPrefix(prefix); } @Data @Accessors(chain = true) static class Options { private StringOpts string; } @Data @Accessors(chain = true) static class StringOpts { private String prefix; } @Data @Accessors(chain = true) static class DefaultUrl { private String url; } }
内容的提问来源于stack exchange,提问作者grav
相关产品推荐
相关产品推荐

