Jackson:如何使用 shorthand 属性 值反序列化 json
Jackson: How to deserialize json with shorthand property value
我正在努力寻找如何使用 Jackson 将遵循 shorthand 约定的 JSON 反序列化为 Java POJO。
[
{
"id":1,
"type": "simple"
},
{
"id":2,
"type": { "kind": "simple" }
},
{
"id":3,
"type": {
"kind": "complex",
"someOtherThing": "value"
}
}
]
这里的"type" 属性可以是字符串也可以是对象。如果它是一个字符串,那么它被认为是具有默认属性的同一对象的简单 shorthand 形式。 IE。上面例子中的1和2是等价的
据我了解,可以为整个 'type' 对象编写自定义反序列化程序。据我所知,在那种情况下,我将不得不手动反序列化整个 'type' 对象。但我真的只想手动处理 shorthand 表单并将正常处理委托给基于注释的映射器。这可能吗?
您可以简单地定义一个带有参数的构造函数,该构造函数将创建具有简单类型的对象。在你的情况下,你的 Type
class 将有一个 String
构造函数。不要忘记也包含一个 noargs 构造函数。
public static void main(String [] args) throws JsonParseException, JsonMappingException, IOException {
String str = "[ {\"id\":1,\"type\":\"simple\" }, {\"id\":2,\"type\": {\"kind\":\"simple\" } }, {\"id\":3,\"type\": {\"kind\":\"complex\",\"someOtherThing\":\"value\" } }]";
ObjectMapper mapper = new ObjectMapper();
MyObject[] objs = mapper.readValue(str.getBytes(), MyObject[].class);
for(MyObject obj : objs) {
System.out.println(obj.id + " " + obj.type.kind + " " + obj.type.someOtherThing);
}
}
public static class MyObject {
public String id;
public Type type;
}
public static class Type {
public String kind;
public String someOtherThing;
public Type() {
}
public Type(String kind) {
this.kind = kind;
}
}
打印出
1 simple null
2 simple null
3 complex value
您可能需要为 type
编写自定义 BeanDeserializer
子类。但是,您可以利用 Jackson 的其余部分来处理类型对象。
您最好的选择是 @JsonIgnore
对象中的类型 属性。然后,在自定义反序列化器中,覆盖 handleIgnoredProperty()
。在这个方法中,做这样的事情:
protected void handleIgnoredProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName)
throws IOException, JsonProcessingException {
if ("type".equals(propName)) {
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
MyObjectDeserializer myObjectDeserializer = (MyObjectDeserializer) ctxt.findRootValueDeserializer(ctxt .getTypeFactory().constructType(MyObject.class));
MyObject myObject = (MyObject) myObjectDeserializer.deserialize(jp, ctxt);
// cast beanOrClass to your object and call object.setType(myObject)
}
else {
// get a StringDeserializer and call object.setType(string)
}
}
else {
super.handleIgnoredProperty(jp, ctxt, beanOrClass, propName);
}
}
您可能需要进行更多处理才能使用 jp.nextToken()
手动读取种类值以到达 someOtherThing
,但我希望这足以让您入门。
我正在努力寻找如何使用 Jackson 将遵循 shorthand 约定的 JSON 反序列化为 Java POJO。
[
{
"id":1,
"type": "simple"
},
{
"id":2,
"type": { "kind": "simple" }
},
{
"id":3,
"type": {
"kind": "complex",
"someOtherThing": "value"
}
}
]
这里的"type" 属性可以是字符串也可以是对象。如果它是一个字符串,那么它被认为是具有默认属性的同一对象的简单 shorthand 形式。 IE。上面例子中的1和2是等价的
据我了解,可以为整个 'type' 对象编写自定义反序列化程序。据我所知,在那种情况下,我将不得不手动反序列化整个 'type' 对象。但我真的只想手动处理 shorthand 表单并将正常处理委托给基于注释的映射器。这可能吗?
您可以简单地定义一个带有参数的构造函数,该构造函数将创建具有简单类型的对象。在你的情况下,你的 Type
class 将有一个 String
构造函数。不要忘记也包含一个 noargs 构造函数。
public static void main(String [] args) throws JsonParseException, JsonMappingException, IOException {
String str = "[ {\"id\":1,\"type\":\"simple\" }, {\"id\":2,\"type\": {\"kind\":\"simple\" } }, {\"id\":3,\"type\": {\"kind\":\"complex\",\"someOtherThing\":\"value\" } }]";
ObjectMapper mapper = new ObjectMapper();
MyObject[] objs = mapper.readValue(str.getBytes(), MyObject[].class);
for(MyObject obj : objs) {
System.out.println(obj.id + " " + obj.type.kind + " " + obj.type.someOtherThing);
}
}
public static class MyObject {
public String id;
public Type type;
}
public static class Type {
public String kind;
public String someOtherThing;
public Type() {
}
public Type(String kind) {
this.kind = kind;
}
}
打印出
1 simple null
2 simple null
3 complex value
您可能需要为 type
编写自定义 BeanDeserializer
子类。但是,您可以利用 Jackson 的其余部分来处理类型对象。
您最好的选择是 @JsonIgnore
对象中的类型 属性。然后,在自定义反序列化器中,覆盖 handleIgnoredProperty()
。在这个方法中,做这样的事情:
protected void handleIgnoredProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName)
throws IOException, JsonProcessingException {
if ("type".equals(propName)) {
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
MyObjectDeserializer myObjectDeserializer = (MyObjectDeserializer) ctxt.findRootValueDeserializer(ctxt .getTypeFactory().constructType(MyObject.class));
MyObject myObject = (MyObject) myObjectDeserializer.deserialize(jp, ctxt);
// cast beanOrClass to your object and call object.setType(myObject)
}
else {
// get a StringDeserializer and call object.setType(string)
}
}
else {
super.handleIgnoredProperty(jp, ctxt, beanOrClass, propName);
}
}
您可能需要进行更多处理才能使用 jp.nextToken()
手动读取种类值以到达 someOtherThing
,但我希望这足以让您入门。