原址:http://www.studytrails.com/java/json/jackson-create-json.jsp
Jackson - Creating JSON from Java
Jackson提供了一些类实现JSON和JAVA对象的互相转换,在这个例子里我们将看到怎样通过JAVA对象来创建JSON结构。我们将从一个简单的类开始,然后逐渐在它的基础上加大复杂度。现在设想我们是一个音乐公司并且我们想发布一个api帮助用户查询唱片。首先我们创建一个只有单个属性的Album类- class Album {
- private String title;
- public Album(String title) {
- this.title = title;
- }
- public String getTitle() {
- return title;
- }
- }
我们使用ObjectMapper类将这个JAVA对象转为JSON,默认情况下,Jackson将会使用BeanSerializar来序列化这个POJO。这是到目前为止我们的序列化器的样子。注意JavaBean必须为私有变量写一个getter方法或者将它定义为public,Here's how theJSON looks:
- {"title":"Kind Of Blue"}
现在我们来为Album增加一个私有变量Link数组(并为它提供getter/setter方法),它将在按压或者查看专辑评论时用到。
- private String[] links;
在主方法里加入这句:
- album.setLinks(new String[] { "link1", "link2" });
现在JSON长这样,注意数组将会被转换成Json array
- {"title":"Kind Of Blue","links":["link1","link2"]}
下一步我们为Album增加一个名为songs的List
- List<String>> Songs = new ArrayList<String>();
为Album对象加入List
- List<String> songs = new ArrayList<String>();
- songs.add("So What");
- songs.add("Flamenco Sketches");
- songs.add("Freddie Freeloader");
- album.setSongs(songs);
- {"title":"Kind Of Blue","links":["link1","link2"],
- "songs":["So What","Flamenco Sketches","Freddie Freeloader"]}
下一步我们为Album加入一个artist,Artist是一个类,包含歌手的名字和他的生日,生日用Date对象表示。注意Artist是一个对象,所以在JSON里应该以一对"{}"括起来,这是JSON对象的表示方式并且"{}"包含key-value键值对,为了让程序简单一点,我们把Artist的成员变量声明为public
- class Artist {
- public String name;
- public Date birthDate;
- }
现在我们把Artist加入album
- 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);
到目前为止JSON长这样:
- {"title":"Kind Of Blue","links":["link1","link2"],
- "songs":["So What","Flamenco Sketches","Freddie Freeloader"],
- "artist":{"name":"Miles Davis","birthDate":-1376027600000}}
为了使JSON看起来更易读一点,我们可以通过以下方法,注意这个方法应该只被用于开发和测试阶段,而不应该用于一个已经发布的程序,因为它会增加JSON的体积。
- mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
- {
- "title" : "Kind Of Blue",
- "links" : [ "link1" , "link2" ],
- "songs" : [ "So What", "Flamenco Sketches", "Freddie Freeloader" ],
- "artist" : {
- "name" : "Miles Davis",
- "birthDate" : -1376027600000
- }
- }
- private Map<String,String> musicians = new HashMap<String, String>();
- 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");
JSON现在长这样:
- {
- "title" : "Kind Of Blue",
- "links" : [ "link1", "link2" ],
- "songs" : [ "So What", "Flamenco Sketches", "Freddie Freeloader" ],
- "artist" : {
- "name" : "Miles Davis",
- "birthDate" : -1376027600000
- },
- "musicians" : {
- "Julian Adderley" : "Alto Saxophone",
- "Paul Chambers" : "double bass",
- "Miles Davis" : "Trumpet, Band leader"
- }
- }
现在让我们来为这个转换加入更多新特性,首先我们要让mapper用它自带的方法来让Map依据键有序排列:
- mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
- SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
- mapper.setDateFormat(outputFormat);
- mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
- @Override
- public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
- if (field.getFullName().equals("com.studytrails.json.jackson.Artist#name"))
- return "Artist-Name";
- return super.nameForField(config, field, defaultName);
- }
- @Override
- public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
- if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))
- return "Album-Title";
- return super.nameForGetterMethod(config, method, defaultName);
- }
- });
- public int age;
- public String homeTown;
- public List<String> awardsWon = new ArrayList<String>();
- "age" : 0,
- "homeTown" : null,
- "awardsWon" : [ ]
- mapper.setSerializationInclusion(Include.NON_EMPTY);
下面是完整的例子:
- package com.studytrails.json.jackson;
- import java.io.IOException;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import com.fasterxml.jackson.annotation.JsonInclude.Include;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.PropertyNamingStrategy;
- import com.fasterxml.jackson.databind.SerializationFeature;
- import com.fasterxml.jackson.databind.cfg.MapperConfig;
- import com.fasterxml.jackson.databind.introspect.AnnotatedField;
- import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
- public class SerializationExample {
- public static void main(String[] args) throws IOException, ParseException {
- ObjectMapper mapper = new ObjectMapper();
- Album album = new Album("Kind Of Blue");
- album.setLinks(new String[] { "link1", "link2" });
- List<string> songs = new ArrayList<string>();
- songs.add("So What");
- songs.add("Flamenco Sketches");
- songs.add("Freddie Freeloader");
- album.setSongs(songs);
- 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);
- album.addMusician("Miles Davis", "Trumpet, Band leader");
- album.addMusician("Julian Adderley", "Alto Saxophone");
- album.addMusician("Paul Chambers", "double bass");
- mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
- mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
- SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
- mapper.setDateFormat(outputFormat);
- mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
- @Override
- public String nameForField(MapperConfig<!--?--> config, AnnotatedField field, String defaultName) {
- if (field.getFullName().equals("com.studytrails.json.jackson.Artist#name"))
- return "Artist-Name";
- return super.nameForField(config, field, defaultName);
- }
- @Override
- public String nameForGetterMethod(MapperConfig<!--?--> config, AnnotatedMethod method, String defaultName) {
- if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))
- return "Album-Title";
- return super.nameForGetterMethod(config, method, defaultName);
- }
- });
- mapper.setSerializationInclusion(Include.NON_EMPTY);
- mapper.writeValue(System.out, album);
- }
- }
- class Album {
- private String title;
- private String[] links;
- private List<string> songs = new ArrayList<string>();
- private Artist artist;
- private Map<string ,="" string=""> musicians = new HashMap<string ,="" string="">();
- public Album(String title) {
- this.title = title;
- }
- public String getTitle() {
- return title;
- }
- public void setLinks(String[] links) {
- this.links = links;
- }
- public String[] getLinks() {
- return links;
- }
- public void setSongs(List<string> songs) {
- this.songs = songs;
- }
- public List<string> getSongs() {
- return songs;
- }
- public void setArtist(Artist artist) {
- this.artist = artist;
- }
- public Artist getArtist() {
- return artist;
- }
- public Map<string ,="" string=""> getMusicians() {
- return Collections.unmodifiableMap(musicians);
- }
- public void addMusician(String key, String value) {
- musicians.put(key, value);
- }
- }
- class Artist {
- public String name;
- public Date birthDate;
- public int age;
- public String homeTown;
- public List<string> awardsWon = new ArrayList<string>();
- }
这是第一部分,关于如何将JAVA对象转换为JSON。
第二部分将讲解如何通过树来创建JSON。
Jackson - Creating JSON Using a TreeModel
通过一个简单的树模型来创建JSON也是可以的,当你不想为你的JSON创建许多类时,这个方法非常有用。我们将使用上面那个例子,一个包含了songs数组、artist对象和musicians数组的,为了创建一个树你首先需要:
- 创建一个JsonNodeFactory来创建节点
- 通过JsonFactory创建一个JsonGenerator并且指定输出方法。在这个例子中我们输出到console
- 它将使用jsonGenerator和树的根节点来创建JSON
完成上述步骤后我们为album创建一个单独的根节点,注意默认情况下mapper不会为这个根节点命名。
- package com.studytrails.json.jackson;
- import java.io.IOException;
- import com.fasterxml.jackson.core.JsonFactory;
- import com.fasterxml.jackson.core.JsonGenerator;
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.node.JsonNodeFactory;
- public class SerializationExampleTreeModel {
- public static void main(String[] args) throws IOException {
- // Create the node factory that gives us nodes.
- JsonNodeFactory factory = new JsonNodeFactory(false);
- // create a json factory to write the treenode as json. for the example
- // we just write to console
- JsonFactory jsonFactory = new JsonFactory();
- JsonGenerator generator = jsonFactory.createGenerator(System.out);
- ObjectMapper mapper = new ObjectMapper();
- // the root node - album
- JsonNode album = factory.objectNode();
- mapper.writeTree(generator, album);
- }
- }
This prints
{}这么一大堆代码只是输出了一对符号!但是,现在才是看看怎么创建我们自己的json的时候,我们首先加入我们的第一个属性'Album-Title'.
- album.put("Album-Title", "Kind Of Blue");
{"Album-Title":"Kind Of Blue"}现在我们加上links数组
- ArrayNode links = factory.arrayNode();
- links.add("link1").add("link2");
- album.put("links", links);
{"Album-Title":"Kind Of Blue","links":["link1","link2"]}下一步我们加上artist对象
- ObjectNode artist = factory.objectNode();
- artist.put("Artist-Name", "Miles Davis");
- artist.put("birthDate", "26 May 1926");
- album.put("artist", artist);
{"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.put("musicians", musicians);
{"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"}}类似的你可以加入其它元素,如果你拥有许多个album,并且你希望通过一个for循环把它们放在一个数组里,显然从JAVA对象创建JSON会比较快。
下一课是Jackson - Creating JSON Stream
PO主自己的总结:
1.Jackson将Java Bean对象转为JSON,只要将这个对象的所有值都确定之后,再调用ObjectMapper类的writeValue方法指定输出流和JavaBean对象即可。
2.如果你不想这么做,也可以以树模型的方式将JAVA对象转为JSON。这样的方式需要用到根节点和JsonGenerator,试想一下这个树模型,我们用put方法将结点添加为根节点的子节点,最终生成了一棵逻辑存在的树,然后调用mapper.writeTree()传入JsonGenerator对象和根节点,在指定输出流里输出了JSON。
- //首先我们需要一个根节点,这里使用的是构造器,但我查api的时候发现JsonNodeFactory有一个instance字段,是全局唯一的,也就是单例的,不知道该用哪个,有待高人解//答
- JsonNodeFactory factory = new JsonNodeFactory(false);
- JsonNode album = factory.objectNode();
- //然后创建一个JsonGenerator对象
- JsonGeneratory generator = new JsonFactory().createGenerator(System.out);
- //创建JsonNode节点
- ObjectNode artist = factory.objectNode();
- artist.put("Artist-Name", "Miles Davis");
- artist.put("birthDate", "26 May 1926");
- //把节点加到album上去
- album.put("artist", artist);
- //通过树模型生成JSON
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeTree(generator,album);
顺便附赠一下Jackson的jar包:http://pan.baidu.com/s/1sjnxJHF