假设我正在为某个类编写自定义序列化,但希望使用默认方法处理其中一个字段。
怎么做?
序列化时我们有JsonGenerator#writeObjectField()
。
但反序列化的对应方法是什么?
请注意以下代码:
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.IOException;
import java.util.Objects;
public class TryDelegate {
public static class MyOuterClassSerializer extends JsonSerializer<MyOuterClass> {
@Override
public void serialize(MyOuterClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeStartObject();
gen.writeObjectField("inner", value.getInner());
gen.writeEndObject();
}
}
public static class MyOuterClassDeserializer extends JsonDeserializer<MyOuterClass> {
@Override
public MyOuterClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
MyOuterClass ans = new MyOuterClass();
JsonToken token;
token = p.getCurrentToken();
if( token != JsonToken.START_OBJECT ) {
throw new JsonParseException("Start object expected", p.getCurrentLocation());
}
if( !"inner".equals(p.nextFieldName() ) ) {
throw new JsonParseException("'inner; field expected", p.getCurrentLocation());
}
MyInnerClass inner = null;// how to desrialize inner from here with default processing???
ans.setInner(inner);
token = p.nextToken();
if( token != JsonToken.END_OBJECT ) {
throw new JsonParseException("End object expected", p.getCurrentLocation());
}
return ans;
}
}
public static class MyInnerClass {
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "{\"value\":" + value + "}";
}
}
@JsonDeserialize(using = MyOuterClassDeserializer.class)
@JsonSerialize(using = MyOuterClassSerializer.class)
public static class MyOuterClass {
private MyInnerClass inner;
public MyInnerClass getInner() {
return inner;
}
public void setInner(MyInnerClass inner) {
this.inner = inner;
}
@Override
public String toString() {
return "{\"inner\":" + Objects.toString(inner) + "}";
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String string;
MyInnerClass inner = new MyInnerClass();
inner.setValue(12);
MyOuterClass outer = new MyOuterClass();
outer.setInner(inner);
string = mapper.writeValueAsString(outer);
System.out.println(string);
MyOuterClass outer2 = mapper.readValue(string, MyOuterClass.class);
System.out.println(outer2); // inner was not deserialized
}
}
如何实施MyOuterDeserializer
?
答案 0 :(得分:6)
DeserializationContext
提供了这些工具。
检查"inner"
的字段名称后,移动到下一个标记,即JSON对象的开头,并使用DeserializationContext
将JSON对象反序列化为MyInnerClass
对象。 / p>
if (!"inner".equals(p.nextFieldName())) {
throw new JsonParseException("'inner; field expected", p.getCurrentLocation());
}
p.nextToken(); // consumes the field name token
MyInnerClass inner = ctxt.readValue(p, MyInnerClass.class);
javadoc陈述
复合材料或容器可以使用的便捷方法 反序列化器,用于读取包含的一次性值(对于序列,它 实际上为整体提取一次反序列化器效率更高 集合)。
使用DeserializationContext
时要小心。不要尝试递归反序列化已注册自定义反序列化器的类型。