Jackson之JSON包的使用分析

    xiaoxiao2025-10-20  4

    引言: JSON的流行推动了JSON开发包的大量使用,如何高效、简便的开发json字符串的输入和输出,是我们在开发中经常会碰到的问题,这里我们以jackson2为例来讲解如何使用它。

    1.  Jackson的版本以及maven依赖

      Jackson的最新版本是2.8.1,  以下是在maven项目中的依赖信息:

    <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.1</version> </dependency>   在以下示例代码中使用的一个依赖包是apache-common中的lang增强包:

    <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> 2.   使用示例

        实体类定义:

    @JsonInclude(JsonInclude.Include.NON_EMPTY) public class JSONCaseA { @JsonProperty("testa") private int age; @JsonIgnore private String unknownAttr; private String location; private String city; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getUnknownAttr() { return unknownAttr; } public void setUnknownAttr(String unknownAttr) { this.unknownAttr = unknownAttr; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String toString() {         return ReflectionToStringBuilder.toString(this);     } }2.1 将对象转换为json字符串

    测试代码:

    public class TestWriteJson { @Test public void writeJson() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); JSONCaseA case1 = new JSONCaseA(); case1.setCity("BeiJing"); case1.setUnknownAttr("testVal"); case1.setAge(123); String jsonStr = mapper.writeValueAsString(case1); System.out.println("JSON:" + jsonStr); } }  结果输出为: JSON:{"city":"BeiJing","testa":123}

      代码中使用的标注分析:

       @JsonProperty("xxx"):  将当前的属性名在json字符串中重新命名为当前设置的这个值,比如在示例中,将age-->testa   @JsonIgnore    将被标注的属性在生成json字符串的时候,直接忽略   @JsonInclude  是一个类级别的设置,JsonInclude.Include.NON_EMPTY标识只有非NULL的值才会被纳入json string之中,其余的都被忽略,比如这里的location属性,并没有出现在最终的结果字符串中。

        2.2  根节点以及使用

         实体类定义:

    @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonRootName(value="rootNode") public class JsonCaseB { @JsonRawValue private String address = "$#"; private int age; @JsonIgnore private String sex; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String toString() {         return ReflectionToStringBuilder.toString(this);      } }   测试代码: public class TestRootNode { @Test public void testRootNode() throws JsonProcessingException { JsonCaseB caseb = new JsonCaseB(); ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); caseb.setAge(123); caseb.setSex("Boy"); String jsonStr = mapper.writeValueAsString(caseb); System.out.println("JSON:" + jsonStr); } }  输出结果:JSON:{"rootNode":{"address":$#,"age":123}}   关于其中使用的annotation的说明:

      @JsonRootName(value="rootNode")   使用在类上,标注为该类在转换为json string的时候,需要新增一个根节点rootNode.   mapper.enable(SerializationFeature.WRAP_ROOT_VALUE):  在mapper级别设置为使用root node方可输出根节点,否则根节点无效。

       2.3 读取操作

          测试代码:

    @Test public void testReadJson() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); String inputjsonstr = "{\"city\":\"BeiJing\",\"testa\":123}"; JSONCaseA readcase = mapper.readValue(inputjsonstr, JSONCaseA.class); System.out.println("object info:" + readcase); }  输出结果:  object info:org.homework.test.json.JSONCaseA@7d907bac[age=123,unknownAttr=<null>,location=<null>,city=BeiJing]

       结果分析:

        json字符串中有2个属性, 目标对象中有4个属性,这个四个属性包含了json字符串中的2个属性;可以发现在JSONCaseA中的属性使用了缺省值,可以正常解析出来结果。

    2.4  在读取过程中,如果json字符串中出现未知属性

        测试代码:

    @Test public void testReadJson() throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); String inputjsonstr = "{\"city\":\"BeiJing\",\"testa\":123, \"who\":\"zhangsan\"}"; JSONCaseA readcase = mapper.readValue(inputjsonstr, JSONCaseA.class); System.out.println("object info:" + readcase); }    输出结果: Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "who" (class org.homework.test.json.JSONCaseAReadUnknowAttr), not marked as ignorable (3 known properties: "city", "location", "testa"]) at [Source: {"city":"BeiJing","testa":123, "who":"zhangsan"}; line: 1, column: 39] (through reference chain: org.homework.test.json.JSONCaseAReadUnknowAttr["who"]) at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62) at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:833) at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1096) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1467) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1445) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833) at org.homework.test.json.JSONCaseAReadUnknowAttr.main(JSONCaseAReadUnknowAttr.java:81)  结果分析: 异常中提示未知属性who,无法解析。

      那么该如何来解决这个问题呢? 新如下设置语句:

    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);  这个设置将禁止使用出现未知属性之时,抛出异常。

       重新执行代码,就可以正常使用了。

    3. 其他相关的Annotation

       @JsonSerialize 使用自定义的类来实现自定义的字段转换。写入操作。   @JsonDeserialize 解析的时候,自定义的转换器;读取操作。   @JsonAutoDetect: 设置类的访问策略,是否所有的属性都可以,还是按照一定的方式来提取。   @JsonRawValue:   无转换的将属性值写入到json 字符串中。 写入操作   @JsonValue:     标注方法,用以替代缺省的方法,由该方法来完成json的字符输出。

          当然还有很多其他的标注,这里不再一一赘述,感兴趣或者需要的话,大家可以自行查找学习。 另外,jackson本身是支持xml和json两种输出的,基于同一套类库。

    4.  参考资料

      http://tutorials.jenkov.com/java-json/jackson-annotations.html#jsonautodetect http://www.baeldung.com/jackson-annotationshttps://github.com/FasterXML/jackson-databind/wiki/Databind-Annotations
    转载请注明原文地址: https://ju.6miu.com/read-1303354.html
    最新回复(0)