如何在jsonschema2pojo中处理多类型字段而非生成Object类型
处理jsonschema2pojo中多类型JSON字段的最优方案
问题背景
在jsonschema2pojo处理遗留JSON数据时,遇到字段支持多种类型的场景(如foo字段既可为字符串,也可为字符串数组),目前生成的Java字段只能是java.lang.Object,希望找到更优处理方式,避免通过子类继承做类型转换。
已尝试的无效方案
- 单独指定
foo的type为string或array:仅能适配单一类型,无法兼容两种格式的遗留数据{ "type":"object", "properties": { "foo": { "type": "string" } } }{ "type":"object", "properties": { "foo": { "type": "array" } } } - 指定
existingJavaType为java.util.List<String>:生成的代码无法解析字符串类型的foo值,会抛出类型转换异常{ "type": "object", "properties": { "foo": { "existingJavaType": "java.util.List<String>" } } }
当前临时方案
不指定foo的类型,生成的Java字段为Object类型,但后续需手动处理类型判断,代码冗余:
{ "type":"object", "properties": { "foo": { } } }
生成的Java类:
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "foo" }) @Generated("jsonschema2pojo") public class Example { @JsonProperty("foo") public Object foo; }
推荐的最优方案
方案1:JSON Schema + 自定义Jackson反序列化器
在Schema中用oneOf声明字段支持的多类型,同时通过jsonschema2pojo配置添加Jackson反序列化注解,自动完成类型转换:
{ "type": "object", "properties": { "foo": { "oneOf": [ {"type": "string"}, {"type": "array", "items": {"type": "string"}} ] } }, "x-jsonschema2pojo": { "annotations": true, "customAnnotations": { "foo": "@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = FooDeserializer.class)" } } }
自定义反序列化器FooDeserializer,统一将输入转为List<String>:
public class FooDeserializer extends JsonDeserializer<List<String>> { @Override public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isTextual()) { return Collections.singletonList(node.asText()); } else if (node.isArray()) { List<String> list = new ArrayList<>(); for (JsonNode item : node) { list.add(item.asText()); } return list; } return null; } }
生成的Example类中foo字段会是List<String>类型,Jackson反序列化时自动完成类型适配,无需业务代码额外处理。
方案2:修改生成类的Setter方法(轻量快速)
如果不想自定义反序列化器,可直接修改生成的Java类,在Setter中做类型转换:
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "foo" }) @Generated("jsonschema2pojo") public class Example { private List<String> foo; @JsonProperty("foo") public void setFoo(Object foo) { if (foo instanceof String) { this.foo = Collections.singletonList((String) foo); } else if (foo instanceof List) { this.foo = (List<String>) foo; } } @JsonProperty("foo") public List<String> getFoo() { return foo; } }
这种方式直接在生成类中统一输出类型,避免后续业务代码做类型判断。若生成频率高,也可通过扩展jsonschema2pojo的模板规则,让代码自动生成该逻辑。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

