jackson

今天在其他项目里面看到有人用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的解析速率

Paste_Image.png

测试总结:

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;
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容