主页 > 其他  > 

jackson:JSON字符串(String)类型的成员序列化和反序列化

jackson:JSON字符串(String)类型的成员序列化和反序列化

对于如下类型定义TestTaskInfo,props字段为JSON字符串(这在数据库经常用到),可以自由保存各种类型的数据

@Data public class TestTaskInfo { private String id; private String props; public TestTaskInfo() { } public TestTaskInfo(String id, String props) { super(); this.id = id; this.props = props; } }

如果对这样的字段直接序列化,效果就是这样:

TestTaskInfo info= new TestTaskInfo("0000", "{\"task_name\":\"RESET\",\"target_id\":22}"); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(info); System.out.println(json);

输出

{"id":"0000","props":"{\"task_name\":\"RESET\",\"target_id\":22}"}

这个结果props字段被序列化为字符串,如果送给前端并不友好,前端还需要再对props字段进行解析才能得到里面的值。

@JsonRawValue

jackson的注解com.fasterxml.jackson.annotation.JsonRawValue可以解决上面的问题,它指示应按原样包含属性的文字字符串值来序列化字段。 所以给props字段增加@JsonRawValue就可以在序列化时将它不加双引号号,直接输出一个JSON对象而非字符串

@Data public class TestTaskInfo { private String id; @JsonRawValue private String props; public TestTaskInfo() { } public TestTaskInfo(String id, String props) { super(); this.id = id; this.props = props; } }

效果是这样:

TestTaskInfo info= new TestTaskInfo("0000", "{\"task_name\":\"RESET\",\"target_id\":22}"); ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); String json = mapper.writeValueAsString(info); System.out.println(json);

输出:

{ "id" : "0000", "props" : {"task_name":"RESET","target_id":22} } RawJsonDeserializer

解决了JSON字符串(String类型)字段序列化的问题,那么反序列化的问题又来了。

{ "id" : "0000", "props" : {"task_name":"RESET","target_id":22} }

上面的输出在反序列化为TestTaskInfo对象时就会出问题,因为props的类型是String,但这个JSON中props是个OBJECT,所以在反序列化时会报错

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token

要解决反序列化的问题,就得实现自定义的反序列化器。不论输入的JSON类型是什么,直接将内容段反序列化为String。这样就与props字段的类型匹配了。

以下是自定义反序列化器的实现:

import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** * Deserializing JSON property as String with Jackson<br> * 实现将有{@link com.fasterxml.jackson.annotation.JsonRawValue}注解的 * 内容为JSON的String类型字段反序列化为String的反序列化器实现 * */ public class RawJsonDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = (ObjectMapper) jp.getCodec(); JsonNode node = mapper.readTree(jp); /** 将节点树输出为String */ return mapper.writeValueAsString(node); } }

我们再修改TestTaskInfo类型定义为props字段增加注解定义反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import gu.sql2java.json.RawJsonDeserializer; import lombok.Data; @Data public class TestTaskInfo { private String id; @JsonRawValue @JsonDeserialize(using = RawJsonDeserializer.class) private String props; public TestTaskInfo() { } public TestTaskInfo(String id, String props) { super(); this.id = id; this.props = props; } }

再次测试:

import static org.junit.Assert.*; import org.junit.Test; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; public class RawJsonDeserializerTest { @Test public void testJacksonCodec() { try { TestTaskInfo info= new TestTaskInfo("0000", "{\"task_name\":\"RESET\",\"target_id\":22}"); ObjectMapper mapper = new ObjectMapper()/* .enable(SerializationFeature.INDENT_OUTPUT) */; /** 序列化 */ String json = mapper.writeValueAsString(info); System.out.println(json); /** 反序列化 */ TestTaskInfo parsed = mapper.readValue(json, TestTaskInfo.class); System.out.println(parsed.toString()); assertTrue(parsed.equals(info)); } catch (Throwable e) { e.printStackTrace(); fail(); } } }

这样就可以正常反序列化了, 输出

{“id”:“0000”,“props”:{“task_name”:“RESET”,“target_id”:22}} TestTaskInfo(id=0000, props={“task_name”:“RESET”,“target_id”:22})

参考资料

《Deserializing JSON property as String with Jackson》

标签:

jackson:JSON字符串(String)类型的成员序列化和反序列化由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“jackson:JSON字符串(String)类型的成员序列化和反序列化