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);- void writeValue(File arg0, Object arg1)
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.序列化和反序列化都生效的注解
-
- @JsonIgnore
作用:告诉 Jackson 在处理时忽略该注解标注的 java pojo(简单java对象) 属性,特别的,json反序列化的时候被忽略的属性会被设置为空。
- 2. @JsonIgnoreProperties
作用:和@JsonIgnore相同,但是是作用在类级别的,可同时设置多个属性
@JsonIgnoreProperties(value={"desc"})
public class SomeEntity {
private String name;
@JsonIgnore
private String desc;
//getter,setter 等省略
}
-
- @JsonIgnoreType
作用:@JsonIgnoreType 标注在类上,当其他类有该类作为属性时,该属性将被忽略
@JsonIgnoreType
public class SomeOtherEntity {
private Long id;
}
public class SomeEntity {
private String name;
private String desc;
private SomeOtherEntity entity;
}
-
- @JsonProperty
作用:可以指定某个属性和json映射的名称。
public class SomeEntity {
@JsonProperty("user_name")
private String userName;
// ...
}
-
- @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 属性。
本文由同组同事黄春宁所做。