jackson使用入门

jackson是java中最常用的json处理工具包之一,其他类似功能的包括gson和fastjson等。本文将简单介绍jackson的基础知识,以作为各位读者未来使用的参考。

三种使用方式

jackson有三种处理json的方式,分别为

  • data binding
  • tree model
  • streaming api

data binding

这种方式可以在json字符串和pojo对象之间直接进行转换。比如说我们有一个json字符串

{"firstName":"dizzy","lastName":"dwarf"}

通过这种方式我们可以直接将其转换成一个Person类的实例,其中firstName和lastName是Person类定义的两个成员变量。

ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(jsonStr, Person.class);

tree model

这种方式类似于xml的DOM解析,在json字符串和DOM树之间进行转换,DOM树的节点是JsonNode类型。其优点在于以统一的方式看待json字符串中的各个部分,使用起来更灵活。

ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(jsonStr);
JsonNode firstName = root.path("firstName");

构建DOM树

如何构建JsonNode的DOM树呢?JsonNode是抽象类,需要使用ObjectNodeArrayNode等子类。

ObjectNode objectNode = objectMapper.createObjectNode();
ArrayNode arrayNode = objectMapper.createArrayNode();

streaming api

这种方式类似于xml的SAX解析,每次处理一个事件,或者这里叫token更合适。

streaming api反序列化

反序列化用的是JsonParser,它的使用方式和迭代器非常相似。你每次处理的都是一个token,比如说在上面这个json字符串中,包括{、firstName、dizzy、lastName、dwarf、}等6个token,通过调用nextToken方法可以获得下一个token。

streaming api序列化

序列化用的JsonGenerator,它的方法都非常直观,比如说writeStartObjectwriteStringFieldwriteEndObject等,这里就不具体介绍了。

注解

通过注解可以定制jackson的各种特性,这里只介绍最常用的几个。

序列化注解

  • @JsonGetter
    注解在方法上,将方法返回的值作为字段序列化的值
public class Person {
    private String firstName;

    @JsonGetter("firstName")
    public String getFirstName() {
        return firstName + "_modified";
    }
    // 省略了setter方法
}

这样一个firstName为"dizzy"的Person序列化后就变成了

{"firstName":"dizzy_modified"}
  • @JsonSerialize
    注解在成员变量上,使用指定的JsonSerializer实现类来序列化这个字段,这个实现类最关键的是serialize方法,这个方法会为你提供JsonGenerator对象作为参数,让你可以通过它来构建序列化后的值。
  • @JsonValue
    注解在方法上,将方法返回的值作为整个对象序列化的结果。

反序列化注解

  • @JsonSetter
    @JsonGetter的逆过程
  • @JsonDeserialize
    @JsonSerialize的逆过程
  • @JsonAlias
    默认情况下java对象中的成员变量名和json字符串的字段名是一对一关系的,但是可能存在这样一种情况。比如firstName这个成员变量,可能json字符串有不同的来源,有的地方这个字段叫firstName,另外一些地方传的字段名称是fName。这个时候就可以用@JsonAlias使这个成员变量接受更多的名称。

通用注解

  • @JsonProperty
    指定该成员变量对应的json字符串的字段名,默认情况下如果两者相同的话不需要使用该注解。
  • @JsonIgnore
    指定该成员变量不参与序列化和反序列化

具体问题解决

下划线和驼峰转换

一般情况下java变量命名采用驼峰方式,而json字符串可能采用下划线方式。解决方式为在类或者成员变量上增加以下注解

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

需要注意的是虽然反序列化的时候first_name会对应到firstName变量,但是序列化的时候也会输出为first_name

多态处理

有时候我们希望根据json字符串中某个字段的取值反序列化成不同的子类,比如说type为1是Student,type为2是Teacher,注意Student和Teacher必须继承同一个父类Person。

@JsonTypeInfo(use = JsonTypeInfo.ID.NAME, property = "type", defaultImpl = Person.class)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Student.class, name = "1"),
    @JsonSubTypes.Type(value = Teacher.class, name = "2")
})
public class Person {}
  • property是决定子类型的字段名称
  • defaultImpl是默认情况下反序列化的类型,这里指的是当type不为1和2时
  • name是子类型对应的字段取值

带泛型参数的List和Map的反序列化

如果我们希望ObjectMapper.readValue返回List<Person>或者Map<String, Person>,由于List<Person>.class和Map<String, Person>.class在java中是不合法的,需要借助于TypeReference

TypeReference<List<Person>> typeReference = new TypeReference<List<Person>>(){};
List<Person> list = objectMapper.readValue(jsonStr, typeReference);

jackson如何集成Spring

Spring提供的MappingJackson2MessageConverter类封装了ObjectMapper,如果希望对ObjectMapper进行定制,可以自己生成一个MappingJackson2MessageConverter对象并注册为bean

只对部分成员变量序列化同时不影响反序列化

有时候我们希望只对部分成员变量进行序列化,如果用@JsonIgnore,会同时影响反序列化。这个时候我们可以用@JsonView注解指定某个视图类的序列化结果包含该成员变量。

更多参考

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

推荐阅读更多精彩内容

  • Jackson JSON工具包包含一组Java注释,您可以使用它们来影响如何将JSON读入对象,或者从对象生成JS...
    谁在烽烟彼岸阅读 7,152评论 0 6
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,072评论 0 3
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,652评论 0 15
  • 孤星明月渐远去, 旭日朝霞方东升。 何来烈火欲烧天, 原是彤云正蔽空。
    无衣客阅读 285评论 2 1