jackson 入门教程

下面演示使用 Jackson 实现 Java 对象和 JSON 的相互转换。

1. 快速参考

1.1 Java object to JSON, writeValue(...)

ObjectMapper mapper = new ObjectMapper();
Staff obj = new Staff();

//Object to JSON in file
mapper.writeValue(new File("c:\\file.json"), obj);

//Object to JSON in String
String jsonInString = mapper.writeValueAsString(obj);

1.2 JSON to Java object readValue(...)

ObjectMapper mapper = new ObjectMapper();
String jsonInString = "{'name' : 'mjw'}";

//JSON from file to Object
Staff obj = mapper.readValue(new File("c:\\file.json"), Staff.class);

//JSON from URL to Object
Staff obj = mapper.readValue(new URL("http://www.jianshu.com/u/c38e94dcec65"), Staff.class);

//JSON from String to Object
Staff obj = mapper.readValue(jsonInString, Staff.class);

2. POJO

Plain Old Java Object, 表示常规的Java对象,没有扩展特定的类,或者实现特定的接口,或者说不受特定框架扩展的影响。

例如,如果想从 JMS 接收信息,则需要实现 MessageListener 接口:

public class ExampleListener implements MessageListener {
  public void onMessage(Message message){
    ...
  }
}

这个类和JMS的 MessageListener 接口绑定,因此难以迁移到其他的信息处理框架,它不是POJO。

3. Java 和 JSON 的相互转换

下面通过一个实例,说明如何使用 Jackson 实现JSON和Java对象相互转换。
Album 类,包含一个字段:

class Album {
    private String title;
    public Album(String title) {
        this.title = title;
    }
    public String getTitle() {
        return title;
    }
}

3.1 使用 ObjectMapper 进行转换

Jackson 默认使用 BeanSerializer 序列化POJO,要求对应的字段为 public,或者有对应的 getter 方法。

单字段序列化
Album album = new Album("Kind Of Blue");
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, album);

输出:

{"title":"Kind Of Blue"}

数组序列化

现在继续向 Album 添加一个数组字段及对应的 getter 和 setter 方法:

private String[] links;
public String[] getLinks(){
    return links;
}
public void setLinks(String[] links){
    this.links = links;
}

修改 main 方法:

Album album = new Album("Kind Of Blue");
album.setLinks(new String[]{"link1", "link2"});
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, album);

输出:

{"title":"Kind Of Blue","links":["link1","link2"]}

List 序列化

向 Album 添加 List 字段:

private List<String> songs;
public List<String> getSongs(){
    return songs;
}
public void setSongs(List<String> songs){
    this.songs = songs;
}

修改 main 方法:

Album album = new Album("Kind Of Blue");
album.setLinks(new String[]{"link1", "link2"});

List<String> songs = new ArrayList<>();
songs.add("So what");
songs.add("Flamenco Sketches");
songs.add("Freddie Freeloader");

album.setSongs(songs);

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, album);

输出:

{"title":"Kind Of Blue","links":["link1","link2"],"songs":["So what","Flamenco Sketches","Freddie Freeloader"]}

从输出结构可以看到,List和数组的输出格式是一样的。

Java 对象序列化

Java 对象,序列化后在JSON中被 {} 括起来。
定义Artist 类:

public class Artist{
    public String name;
    public Date birthDate;
}

在Album 中添加对应的字段,并在 main 中设置其值:

Artist artist = new Artist();
artist.name = "Miles Davis";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
artist.birthDate = format.parse("26-05-1926");
album.setArtist(artist);

输出:

{"title":"Kind Of Blue","links":["link1","link2"],"songs":["So what","Flamenco Sketches","Freddie Freeloader"],"artist":{"name":"Miles Davis","birthDate":-1376035200000}}

格式化输出

配置 ObjectMapper ,可以让输出更好看一些:

mapper.configure(SerializationFeature.INDENT_OUTPUT, true);

此时的JSON输出如下:

{
  "title" : "Kind Of Blue",
  "links" : [ "link1", "link2" ],
  "songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
  "artist" : {
    "name" : "Miles Davis",
    "birthDate" : -1376035200000
  }
}
Map 序列化

向 Album 中添加如下内容:

private Map<String, String> musicians = new HashMap<>();
public Map<String, String> getMusicians(){
    return Collections.unmodifiableMap(musicians);
}
public void addMusician(String key, String value){
    musicians.put(key, value);
}

在 main 中添加如下内容:

album.addMusician("Miles Davis", "Trumpet, Band leader");
album.addMusician("Julian Adderley", "Alto Saxophone");
album.addMusician("Paul Chambers", "double bass");

输出如下:

{
  "title" : "Kind Of Blue",
  "links" : [ "link1", "link2" ],
  "songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
  "artist" : {
    "name" : "Miles Davis",
    "birthDate" : -1376035200000
  },
  "musicians" : {
    "Miles Davis" : "Trumpet, Band leader",
    "Paul Chambers" : "double bass",
    "Julian Adderley" : "Alto Saxophone"
  }
}
其他

设置输出时间格式

SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
mapper.setDateFormat(outputFormat);

让Map按序输出

mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

此时输出:

{
  "title" : "Kind Of Blue",
  "links" : [ "link1", "link2" ],
  "songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
  "artist" : {
    "name" : "Miles Davis",
    "birthDate" : "26 May 1926"
  },
  "musicians" : {
    "Julian Adderley" : "Alto Saxophone",
    "Miles Davis" : "Trumpet, Band leader",
    "Paul Chambers" : "double bass"
  }
}

3.2 使用 Tree Model 进行转换

我们继续使用上面的例子,来演示 Tree Model 的使用。使用 Tree 进行输出包含如下几个步骤:

  • 创建 JsonNodeFactory,用于创建 node。
  • 使用JsonFactory创建 JsonGenerator,并指定输出方法。
  • 创建ObjectMapper,它使用 JsonGenerator 和树的根节点输出到JSON。

如下所示:

public class SerializationExampleTreeModel{
    public static void main(String[] args) throws IOException{
        JsonNodeFactory factory = new JsonNodeFactory(false);

        JsonFactory jsonFactory = new JsonFactory();
        JsonGenerator generator = jsonFactory.createGenerator(System.out);

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode album = factory.objectNode();
        mapper.writeTree(generator, album);
    }
}

由于没有添加任何实质性内容,所以输出为:

{}

开始添加内容:

album.put("Album-Title", "Kind Of Blue");

JSON:

{"Album-Title":"Kind Of Blue"}

添加数组:

ArrayNode links = factory.arrayNode();
links.add("link1").add("link2");
album.set("links", links);

JSON:

{"Album-Title":"Kind Of Blue","links":["link1","link2"]}

添加对象:

ObjectNode artist = factory.objectNode();
artist.put("Artist-Name", "Miles Davis");
artist.put("birthDate", "26 May 1926");
album.set("artist", artist);

JSON:

{"Album-Title":"Kind Of Blue","links":["link1","link2"],"artist":{"Artist-Name":"Miles Davis","birthDate":"26 May 1926"}}

添加 musicians:

ObjectNode musicians = factory.objectNode();
musicians.put("Julian Adderley", "Alto Saxophone");
musicians.put("Miles Davis", "Trumpet, Band leader");
album.set("musicians", musicians);

JSON:

{"Album-Title":"Kind Of Blue","links":["link1","link2"],"artist":{"Artist-Name":"Miles Davis","birthDate":"26 May 1926"},"musicians":{"Julian Adderley":"Alto Saxophone","Miles Davis":"Trumpet, Band leader"}}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容