jsonserializer java,如何在Java中创建自定义JsonDeserializer?

I have a Map fieldOfC as a field of a class C. When I try to deserialize C with Jackson, an Exception is thrown because it can't find a Deserializer for Map's key A. So, I guess the solution is to extend StdJsonDeserializer and do it manually.

My problem is that I can't find an example on how to use the parser and the context of the method "deserialize" that I have to implement.

Can anyone write the code for this simple example so I can use it as a start to build my real deserializer?

public class A{

private String a1;

private Integer a2;

}

public class B{

private String b1;

}

public class C{

@JsonDeserialize(keyUsing=ADeserializer.class)

//also tried this: @JsonDeserialize(keyAs=A.class) without success

private Map fieldOfC;

private String c1;

}

public class ADeserializer extends StdKeyDeserializer {

protected ADeserializer(Class cls) {

super(cls);

}

protected Object _parse(String key, DeserializationContext ctxt) throws Exception {

ObjectMapper mapper = new ObjectMapper();

return mapper.readValue(key, A.class);

}

}

Thanks in advance

EDIT: googling, I found a test of the same problem I have. This is exactly my problem

EDIT: changed extended class from StdDeserializer to StdKeyDeserializer as I read here in method findKeyDeserializer(org.codehaus.jackson.map.DeserializationConfig, org.codehaus.jackson.type.JavaType, org.codehaus.jackson.map.BeanProperty)

EDIT: After solving this issue I got this one that is related.

解决方案

I am a complete newbie with Jackson, but the following works for me.

First I add a JsonCreator method to A:

public class A {

private String a1;

private Integer a2;

public String getA1() { return a1; }

public Integer getA2() { return a2; }

public void setA1(String a1) { this.a1 = a1; }

public void setA2(Integer a2) { this.a2 = a2; }

@JsonCreator

public static A fromJSON(String val) throws JsonParseException, JsonMappingException, IOException {

ObjectMapper mapper = new ObjectMapper();

A a = mapper.readValue(val,A.class);

return a;

}

}

That alone solves the deserialization problem. The harder part for me was the correct serialization of the keys. What I did there was to define a key serializer that serializes named classes as there JSON serialization, like this:

public class KeySerializer extends SerializerBase {

private static final SerializerBase DEFAULT = new StdKeySerializer();

private Set> objectKeys_ = Collections.synchronizedSet(new HashSet>());

protected KeySerializer(Class>... objectKeys) {

super(Object.class);

for(Class> cl:objectKeys) {

objectKeys_.add(cl);

}

}

@Override

public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {

return DEFAULT.getSchema(provider, typeHint);

}

@Override

public void serialize(Object value, JsonGenerator jgen,

SerializerProvider provider) throws IOException,

JsonGenerationException {

if (objectKeys_.contains(value.getClass())) {

ObjectMapper mapper = new ObjectMapper();

StringWriter writer = new StringWriter();

mapper.writeValue(writer, value);

jgen.writeFieldName(writer.toString());

} else {

DEFAULT.serialize(value, jgen, provider);

}

}

}

Then to prove it works, serializing and deserializing an instance of class C:

ObjectMapper mapper = new ObjectMapper();

StdSerializerProvider provider = new StdSerializerProvider();

provider.setKeySerializer(new KeySerializer(A.class));

mapper.setSerializerProvider(provider);

StringWriter out = new StringWriter();

mapper.writeValue(out, c);

String json = out.toString();

System.out.println("JSON= "+json);

C c2 = mapper.readValue(json, C.class);

System.out.print("C2= ");

StringWriter outC2 = new StringWriter();

mapper.writeValue(outC2, c2);

System.out.println(outC2.toString());

For me this produced the output:

JSON= {"c1":"goo","map":{"{\"a1\":\"1ccf\",\"a2\":7376}":{"b1":"5ox"},"{\"a1\":\"1cd2\",\"a2\":7379}":{"b1":"5p0"},"{\"a1\":\"1cd5\",\"a2\":7382}":{"b1":"5p3"},"{\"a1\":\"1cd8\",\"a2\":7385}":{"b1":"5p6"}}}

C2= {"c1":"goo","map":{"{\"a1\":\"1ccf\",\"a2\":7376}":{"b1":"5ox"},"{\"a1\":\"1cd2\",\"a2\":7379}":{"b1":"5p0"},"{\"a1\":\"1cd5\",\"a2\":7382}":{"b1":"5p3"},"{\"a1\":\"1cd8\",\"a2\":7385}":{"b1":"5p6"}}}

I feel there ought to have been a better way of doing saying how to serialize the key by using annotations, but I could not work it out.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了自定义JSON序列化和反序列化的方式,可以通过实现`JsonSerializer`和`JsonDeserializer`接口来实现。 自定义JSON序列化: 1. 创建一个类,实现`JsonSerializer`接口,并重写`serialize`方法。在该方法,可以自定义对象的序列化逻辑,将对象转换为JSON格式的字符串。 2. 在需要进行自定义序列化的字段上,使用`@JsonSerialize(using = YourSerializer.class)`注解,将自定义的序列化类指定为该字段的序列化器。 自定义JSON反序列化: 1. 创建一个类,实现`JsonDeserializer`接口,并重写`deserialize`方法。在该方法,可以自定义JSON字符串的反序列化逻辑,将JSON字符串转换为对象。 2. 在需要进行自定义反序列化的字段上,使用`@JsonDeserialize(using = YourDeserializer.class)`注解,将自定义的反序列化类指定为该字段的反序列化器。 示例代码如下: ```java // 自定义序列化器 public class CustomSerializer extends JsonSerializer<YourClass> { @Override public void serialize(YourClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 自定义序列化逻辑 gen.writeString(value.toString()); } } // 自定义反序列化器 public class CustomDeserializer extends JsonDeserializer<YourClass> { @Override public YourClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 自定义反序列化逻辑 String value = p.getValueAsString(); return new YourClass(value); } } // 在需要进行自定义序列化和反序列化的字段上使用注解 public class YourClass { @JsonSerialize(using = CustomSerializer.class) private String field1; @JsonDeserialize(using = CustomDeserializer.class) private String field2; // 省略其他代码 } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值