今天在其他项目里面看到有人用jackson,就试着用了一下,并做点笔记。
一、jackson简介
解析原理:基于事件驱动,与GSON相同,先创建一个对应于JSON数据的JavaBean类就可以通过简单的操作解析出所需JSON数据。但和Gson解析不同的是,GSON可按需解析,即创建的JavaBean类不一定完全涵盖所要解析的JSON数据,按需创建属性,但Jackson解析对应的JavaBean必须把Json数据里面的所有key都有所对应,即必须把JSON内的数据所有解析出来,无法按需解析。但Jackson的解析速度和效率都要比GSON高
二、Jackson、JSON-lib、Gson的比较
网上偷来一张图作为对比Jackson、JSON-lib、Gson的解析速率
测试总结:
1、显而易见,无论是哪种形式的转换,Jackson > Gson > Json-lib。
Jackson的处理能力甚至高出Json-lib有10倍左右
2、JSON-lib似乎已经停止更新,最新的版本也是基于JDK15,而Jackson的社区则较为活跃;
3、在测试性能的同时,又以人肉方式对这三个类库转换的正确性 进行了检查 ,三者均达100%正确 ;
4、JSON-lib在转换诸如Date类型时较为累赘,如以下是两者的转换结果:
JSON-lib:
{"brithday":{"date":17,"day":2,"hours":9,"minutes":24,"month":7,"seconds":26,"time":1282008266398,"timezoneOffset":-480,"year":110}}
Jackson:
{"brithday":1282008123101}
5、JSON-lib依赖commons系列的包及 ezmorph包共 5个,而Jackson除自身的以外只依赖于commons-logging
6、Jackson提供完整基于节点的Tree Model,以及完整的OJM数据绑定功能。
三、jackson的基本使用
1、导入项目
compile 'com.squareup.retrofit2:converter-jackson:2.2.0'
如果这里有冲突报错,这添加下面这段话
android {
...
}
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
}
2、DEMO
package com.ycxc.template.bean;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* Fuction: 网易新闻详情<p>
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class NeteastNewsSummary {
@JsonProperty("postid")
public String postid;
@JsonProperty("hasCover")
public boolean hasCover;
@JsonProperty("hasHead")
public int hasHead;
@JsonProperty("replyCount")
public int replyCount;
@JsonProperty("hasImg")
public int hasImg;
@JsonProperty("digest")
public String digest;
@JsonProperty("hasIcon")
public boolean hasIcon;
@JsonProperty("docid")
public String docid;
@JsonProperty("title")
public String title;
@JsonProperty("order")
public int order;
@JsonProperty("priority")
public int priority;
@JsonProperty("lmodify")
public String lmodify;
@JsonProperty("boardid")
public String boardid;
@JsonProperty("photosetID")
public String photosetID;
@JsonProperty("template")
public String template;
@JsonProperty("votecount")
public int votecount;
@JsonProperty("skipID")
public String skipID;
@JsonProperty("alias")
public String alias;
@JsonProperty("skipType")
public String skipType;
@JsonProperty("cid")
public String cid;
@JsonProperty("hasAD")
public int hasAD;
@JsonProperty("imgsrc")
public String imgsrc;
@JsonProperty("tname")
public String tname;
@JsonProperty("ename")
public String ename;
@JsonProperty("ptime")
public String ptime;
/**
* title : 哈萨克斯坦中亚在建第1高楼爆炸起火
* tag : photoset
* imgsrc : http://img5.cache.netease.com/3g/2016/2/13/2016021318005710210.jpg
* subtitle :
* url : 00AN0001|110630
*/
@JsonProperty("ads")
public List<AdsEntity> ads;
/**
* imgsrc : http://img5.cache.netease.com/3g/2016/2/13/201602131446132dc50.jpg
*/
@JsonProperty("imgextra")
public List<ImgextraEntity> imgextra;
@JsonIgnoreProperties(ignoreUnknown = true)
public static class AdsEntity {
@JsonProperty("title")
public String title;
@JsonProperty("tag")
public String tag;
@JsonProperty("imgsrc")
public String imgsrc;
@JsonProperty("subtitle")
public String subtitle;
@JsonProperty("url")
public String url;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ImgextraEntity {
@JsonProperty("imgsrc")
public String imgsrc;
}
}
四、相关属性介绍
1 排除属性
@JsonIgnore,一般标记在属性或方法上的注解。序列化与反序列化时忽略被该注解修饰的成员。
@JsonIgnoreProperties,如果是代理类,由于无法标记在属性或方法上,所以,可以标记在类声明上;也作用于反序列化时的字段解析;
@JsonIgnoreProperties({"extra"})
类注解。在反序列化 json 数据时能够忽略注解参数中对应的 json keys。
@JsonIgnoreProperties(ignoreUnknown = true)
//Jackson解析JSON数据时,忽略未知的字段。(如果不设置,当JSON字段和bean字段不匹配时,会抛出异常)
2 属性别名
@JsonProperty,序列化/反序列化都有效;
3 属性排序
@JsonPropertyOrder,注释在类声明中;
4 属性格式转换
使用自定义序列化/反序列化来处理;
@JsonSerialize,序列化;
@JsonDeserialize,反序列化;
注意:在使用hibernate的时候,查询数据库后产生的实体类是个代理类,这时候转换JSON会报错;
解决方法有两种:
1)设置FAIL_ON_EMPTY_BEANS属性,告诉Jackson空对象不要抛异常;
mapper.disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
2)使用@JsonIgnoreProperties注解
在实体类声明处加上@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})注解;
建议使用@JsonIgnoreProperties注解,这样生成的JSON中不会产生多余的字段;
@JsonSerialize(using = JacksonUtil.JsonLocalDateSerializer.class)
属性注解。需要使用自定义序列化与反序列化解析器时,使用该注解修饰类成员变量。
5 父/子关联
@JsonManagedReference,放在父亲类中;
@JsonBackReference,放在孩子类中;
6 去掉包装
@JsonUnwrapped,意思如下:
Ability to map JSON like
{
"name" : "home",
"latitude" : 127,
"longitude" : 345
}
to classes defined as:
class Place {
public String name;
@JsonUnwrapped
public Location location;
}
class Location {
public int latitude, longitude;
}
五、JacksonUtil
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
/**
* XML,JSON处理工具类
* 依靠jackson提供pojo2json/xml转换
*
* @author HaiJia
*/
final public class JacksonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
private static ObjectMapper xmlMapper = new XmlMapper();
/**
* 防止反射调用构造器创建对象
*/
private JacksonUtil() {
throw new AssertionError();
}
/**
* 自定义日期序列化处理类
* LocalDateTime
* jdk8 support
*/
public static class JsonLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String localdateTimeStr = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
jsonGenerator.writeString(localdateTimeStr);
}
}
/**
* 自定义日期序列化处理类
* LocalDateTime
* jdk8 support
*/
public static class JsonLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String str = jsonParser.getText().trim();
return LocalDateTime.parse(str, DateTimeFormatter.ISO_DATE_TIME);
}
}
/**
* 自定义日期反序列化处理类
* LocalDate
* jdk8 support
*/
public static class JsonLocalDateDeserializer extends JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String str = jsonParser.getText().trim();
return LocalDate.parse(str, DateTimeFormatter.ISO_DATE);
}
}
/**
* 自定义日期序列化类
* LocalDate
* jdk8 support
*/
public static class JsonLocalDateSerializer extends JsonSerializer<LocalDate> {
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String localdateStr = localDate.format(DateTimeFormatter.ISO_DATE);
jsonGenerator.writeString(localdateStr);
}
}
/**
* json数据转pojo
*
* @param jsonStr json字符串
* @param cls 映射类型
* @param <T> 推导类型
* @return 推导类型json对象
*/
public static <T> T json2Pojo(String jsonStr, Class<T> cls) {
T object = null;
try {
object = objectMapper.readValue(jsonStr, cls);
} catch (IOException e) {
e.printStackTrace();
}
return object;
}
/**
* json数据转PojoList
*
* @param jsonStr json数据
* @param cls 类型
* @param <T> 推导类型
* @return pojoList
*/
public static <T> List<T> jsonArray2PojoList(String jsonStr, Class<T> cls) {
List<T> pojoList = null;
try {
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, cls);
pojoList = objectMapper.readValue(jsonStr, listType);
} catch (IOException e) {
e.printStackTrace();
}
return pojoList;
}
/**
* pojo转json
*
* @param obj pojo
* @return json字符串
*/
public static String pojo2Json(Object obj) {
String jsonStr = "";
try {
jsonStr = objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonStr;
}
/**
* json转listMap
*
* @param jsonArray jsonArray字符串
* @return Listmap对象
*/
public static List<Map<String, Object>> jsonArray2ListMap(String jsonArray) {
List<Map<String, Object>> convertedListMap = null;
try {
convertedListMap = objectMapper.readValue(jsonArray, new TypeReference<List<Map<String, Object>>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
return convertedListMap;
}
/**
* json转map
*
* @param json json字符串
* @return map对象
*/
public static Map<String, Object> json2Map(String json) {
Map<String, Object> convertedMap = null;
try {
convertedMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
return convertedMap;
}
/**
* listMap转json
*
* @param listMap listMap
* @return
*/
public static String listMap2JsonArray(List<Map<String, Object>> listMap) {
String jsonStr = "";
try {
jsonStr = objectMapper.writeValueAsString(listMap);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonStr;
}
/**
* xml转pojo
*
* @param xmlStr xml字符串
* @param cls 映射对象
* @param <T> 推导类型
* @return pojo
*/
public static <T> T xml2Pojo(String xmlStr, Class<T> cls) {
T pojo = null;
try {
pojo = xmlMapper.readValue(xmlStr, cls);
} catch (IOException e) {
e.printStackTrace();
}
return pojo;
}
/**
* xml转pojoList
*
* @param xmlStr xml字符串
* @param cls 映射对象
* @param <T> 推导类型
* @return pojo
*/
public static <T> List<T> xml2PojoList(String xmlStr, Class<T> cls) {
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, cls);
List<T> pojoList = null;
try {
pojoList = xmlMapper.readValue(xmlStr, listType);
} catch (IOException e) {
e.printStackTrace();
}
return pojoList;
}
/**
* pojo转xml
*
* @param object
*/
public static String pojo2Xml(Object object) {
String xml = "";
try {
xml = xmlMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return xml;
}
/**
* xml转map
*
* @param xmlStr xml字符串
* @return map对象
*/
public static Map<String, Object> xml2Map(String xmlStr) {
Map<String, Object> map = null;
try {
map = xmlMapper.readValue(xmlStr, new TypeReference<Map<String, Object>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
/**
* xml转ListMap
*
* @param xmlStr xml字符串
* @return map对象
*/
public static List<Map<String, Object>> xml2ListMap(String xmlStr) {
List<Map<String, Object>> listMap = null;
try {
listMap = xmlMapper.readValue(xmlStr, new TypeReference<List<Map<String, Object>>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
return listMap;
}
}