Jackson json的研究

本文深入探讨了Jackson JSON库,包括其相较于其他JSON库的优势、核心类`ObjectMapper`的使用方法,如对象转JSON和JSON转对象,以及各种序列化和反序列化的注解。还介绍了如何在反序列化时忽略未知属性,以及`@JsonIgnore`、`@JsonIgnoreProperties`、`@JsonProperty`等注解的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STUDY20170731 Jackson json的研究

一、Jackson简述

Java下常见的Json类库有Gson、JSON-lib、Jackson和FastJson。
json-lib是最开始的也是应用最广泛的json解析工具,相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。
- 各个JSON技术的比较
- Jackson API参考

二、利用Jackson进行Json的序列化与反序列化

1.准备工作

首先去官网下载Jackson工具包,下载地址http://wiki.fasterxml.com/JacksonDownload
下载三个jar包或者提供maven依赖:
- jackson-core-2.X.X.jar
- jackson-annotations-2.X.X.jar
- jackson-databind-2.X.X.jar

    <!--http://www.mvnrepository.com/artifact/com.fasterxml.jackson.core -->
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
    </dependency>

2.JSON序列化[java对象转json]

  • ==ObjectMapper==是Jackson操作的核心类,Jackson的所有JSON操作都是在ObjectMapper中实现。
  • ObjectMapper有多个JSON序列化的方法,可以把JSON字符串保存File、OutputStream等不同的介质中。

    • void writeValue(File arg0, Object arg1)
      把arg1转成json序列,并保存到arg0文件中。
    • void writeValue(OutputStream arg0, Object arg1)
      把arg1转成json序列,并保存到arg0输出流中。
    • byte[] writeValueAsBytes(Object arg0)
      把arg0转成json序列,并把结果输出成字节数组。
    • String writeValueAsString(Object arg0)
      把arg0转成json序列,并把结果输出成字符串。参数可以是实体类、集合等

    ObjectMapper mapper = new ObjectMapper();
    //User类转JSON
    //输出结果:{“name”:”小民”,”age”:20,”birthday”:844099200000,”email”:”xiaomin@sina.com”}
    String json = mapper.writeValueAsString(user);

3.JSON的反序列化[json转java对象]

1) JsonNode类介绍
JSON树模型

ObjectMapper mapper = new ObjectMapper();

JsonNode rootNode = mapper.readTree(jsonString); readTree的参数还可以是byte[] File InputStream URL等

常用方法:
JsonNode    get(int index)  常用于集合遍历
JsonNode    get(String fieldName)  通过key获取value
String      asText()    ……
String      toString()
Boolean     isArray()   ……
  • 处理直接的list集合字符串时,可根据需要拿到一层一层的子字符串,再对子字符串进行转换

    形如[
            [
               {
                 expendCodeResource:{},
                 expendResource:{},
                 fixResource:{}
               },
               ……
            ],
            [
               {
                 expendCodeResource:{},
                 expendResource:{},
                 fixResource:{}
               }
            ],
            ……
        ]
      JsonNode node = mapper.readTree(jsonString);
            for(JsonNode nodeOne:node){
                for(JsonNode nodeTwo:nodeOne){
                    String jsonEntity = nodeTwo.get("expendCodeResource").toString();
                }
            }
    另外需注意:通过键拿值的时候,asText()方法拿到的值不带"",toString()方法带""
    即对于{"name":"zhangsan"}
    node.get("name").asText();--->zhangsan
    node.get("name").toString();--->"zhangsan"
    对于{"success":true}则两个的结果一样为true
    

2) ObjectMapper支持从byte[]、File、InputStream、字符串等数据的JSON反序列化。
即 mapper.readValue(src, valueType)

1.转实体类
String json = “{\”name\”:\”zhangsan\”,\”age\”:20,\”birthday\”:844099200000,\”email\”:\”zhangsan@163.com\”}”;
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
2.转集合,参数jsonString应为user对象的list的字符串; 经常搭配JsonNode获取:

JsonNode node = mapper.readTree(jsonString);
jsonString = node.get("data").get("accSeqs").toString();   
//jsonString = "[{},{}]"
关键部分:
    JavaType javaType = mapper.getTypeFactory().constructParametricType(  
                List.class, User.class); 
    List<User> me = mapper.readValue(josnString, javaType);
3.转map
Map m = mapper.readValue(jsonString, Map.class); //json转换成map 
结果:{name=zhangsan, age=20, hhh=zhangsan@163.com} ,m.get("age") --->20
4.转数组   //jsonlist = "[{},{}]"
User[] u = mapper.readValue(jsonlist, User[].class);

3) jackson反序列化时忽略不需要的字段

  • 一般情况,反序列化时,遇到未知属性(那些没有对应的属性来映射的属性,并且没有任何setter或handler来处理这样的属性)时是否引起结果失败(通过抛JsonMappingException异常);
  • 通过设置可以关掉检查 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    特别的,如果json序列中有同名的字段,将取第一个为准
String string ="{\"name\":\"zhangsan\",\"age\":21,\"email\":\"zhangsan@163.com\",\"sex\":true},\"email\":\"zhangsan@162.com\"";
结果:
User{name='zhangsan', age=21, sex=true, birthday=null, email='zhangsan@163.com'}    

三、Jackson注解

1.序列化和反序列化都生效的注解

    1. @JsonIgnore

作用:告诉 Jackson 在处理时忽略该注解标注的 java pojo(简单java对象) 属性,特别的,json反序列化的时候被忽略的属性会被设置为空。
- 2. @JsonIgnoreProperties

作用:和@JsonIgnore相同,但是是作用在类级别的,可同时设置多个属性

    @JsonIgnoreProperties(value={"desc"})
    public class SomeEntity {
    private String name;
    @JsonIgnore
    private String desc;
   //getter,setter 等省略
    }
    1. @JsonIgnoreType

作用:@JsonIgnoreType 标注在类上,当其他类有该类作为属性时,该属性将被忽略

@JsonIgnoreType
public class SomeOtherEntity {
private Long id;

}
public class SomeEntity {
private String name;
private String desc;
private SomeOtherEntity entity;
}
    1. @JsonProperty

作用:可以指定某个属性和json映射的名称。

public class SomeEntity {
@JsonProperty("user_name")
private String userName;
  // ...
}
    1. @JsonFormat

作用:此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)。是指值的格式化:”birthday”:”1997年09月30日”

//格式化日期属性
@JsonFormat(pattern = "yyyy年MM月dd日")
private Date birthday;
得出的jsonString可直接反序列化

2.只在序列化情况下生效的注解

  • @JsonPropertyOrder

作用:在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonPropertyOrder 可以指定属性在 json 字符串中的顺序。

@JsonPropertyOrder(value={"desc","name"})
public class SomeEntity {
private String name;
private String desc;
  //..
}

- @JsonInclude

作用:在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonInclude 注解可以控制在哪些情况下才将被注解的属性转换成 json

例如只有属性不为 null 时:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SomeEntity {
private String name;
private String desc;
}
该注解也可以加在某个字段上。另外还有很多其它的范围,例如 NON_EMPTY、NON_DEFAULT等,具体请参考 jackson api,比较混乱

3.只在反序列化情况下生效的注解

  • @JsonSetter

作用:@JsonSetter 标注于 setter 方法上,类似 @JsonProperty ,也可以解决 json 键名称和 java pojo 字段名称不匹配的问题。

public class SomeEntity {
private String desc;
@JsonSetter("description")
public void setDesc(String desc) {
    this.desc = desc;
}
}
例子中在将 json 字符串转换成 SomeEntity 实例时,会将 json 字符串中的 description 字段赋值给 SomeEntity 的 desc 属性。

本文由同组同事黄春宁所做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值