外网渣翻意会Jackson - Java to JSON and back

来源:互联网 发布:wow60 n服数据库 编辑:程序博客网 时间:2024/05/29 06:54

原址:http://www.studytrails.com/java/json/jackson-create-json.jsp

Jackson - Creating JSON from Java

Jackson提供了一些类实现JSON和JAVA对象的互相转换,在这个例子里我们将看到怎样通过JAVA对象来创建JSON结构。我们将从一个简单的类开始,然后逐渐在它的基础上加大复杂度。现在设想我们是一个音乐公司并且我们想发布一个api帮助用户查询唱片。首先我们创建一个只有单个属性的Album类
[java] view plain copy
 print?
  1. class Album {  
  2.     private String title;  
  3.    
  4.     public Album(String title) {  
  5.         this.title = title;  
  6.     }  
  7.        
  8.     public String getTitle() {  
  9.         return title;  
  10.     }  
  11. }  

我们使用ObjectMapper类将这个JAVA对象转为JSON,默认情况下,Jackson将会使用BeanSerializar来序列化这个POJO。这是到目前为止我们的序列化器的样子。注意JavaBean必须为私有变量写一个getter方法或者将它定义为public,Here's how theJSON looks:

[java] view plain copy
 print?
  1. {"title":"Kind Of Blue"}  

现在我们来为Album增加一个私有变量Link数组(并为它提供getter/setter方法),它将在按压或者查看专辑评论时用到。

[java] view plain copy
 print?
  1. private String[] links;  

在主方法里加入这句:

[java] view plain copy
 print?
  1. album.setLinks(new String[] { "link1""link2" });  

现在JSON长这样,注意数组将会被转换成Json array

[java] view plain copy
 print?
  1. {"title":"Kind Of Blue","links":["link1","link2"]}  

下一步我们为Album增加一个名为songs的List
[java] view plain copy
 print?
  1. List<String>> Songs = new ArrayList<String>();  

为Album对象加入List

[java] view plain copy
 print?
  1. List<String> songs = new ArrayList<String>();  
  2. songs.add("So What");  
  3. songs.add("Flamenco Sketches");  
  4. songs.add("Freddie Freeloader");  
  5. album.setSongs(songs);  
现在JSON长这样,注意List也会被转换成array。You can learn more about List Serialization inthistutorial.

[java] view plain copy
 print?
  1. {"title":"Kind Of Blue","links":["link1","link2"],  
  2. "songs":["So What","Flamenco Sketches","Freddie Freeloader"]}  

下一步我们为Album加入一个artist,Artist是一个类,包含歌手的名字和他的生日,生日用Date对象表示。注意Artist是一个对象,所以在JSON里应该以一对"{}"括起来,这是JSON对象的表示方式并且"{}"包含key-value键值对,为了让程序简单一点,我们把Artist的成员变量声明为public

[java] view plain copy
 print?
  1. class Artist {  
  2.     public String name;  
  3.     public Date birthDate;  
  4. }  

现在我们把Artist加入album

[java] view plain copy
 print?
  1. Artist artist = new Artist();  
  2. artist.name = "Miles Davis";  
  3. SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");  
  4. artist.birthDate = format.parse("26-05-1926");  
  5. album.setArtist(artist);  

到目前为止JSON长这样:

[java] view plain copy
 print?
  1. {"title":"Kind Of Blue","links":["link1","link2"],  
  2. "songs":["So What","Flamenco Sketches","Freddie Freeloader"],  
  3. "artist":{"name":"Miles Davis","birthDate":-1376027600000}}  

为了使JSON看起来更易读一点,我们可以通过以下方法,注意这个方法应该只被用于开发和测试阶段,而不应该用于一个已经发布的程序,因为它会增加JSON的体积。

[java] view plain copy
 print?
  1.       
  2. mapper.configure(SerializationFeature.INDENT_OUTPUT, true);  
现在JSON看起来被很好地格式化了:
[java] view plain copy
 print?
  1. {  
  2.   "title" : "Kind Of Blue",  
  3.   "links" : [ "link1" , "link2" ],  
  4.   "songs" : [ "So What""Flamenco Sketches""Freddie Freeloader" ],  
  5.   "artist" : {  
  6.     "name" : "Miles Davis",  
  7.     "birthDate" : -1376027600000  
  8.   }  
  9. }  
现在我们要创建一个Map,为音乐家和他们在歌曲中使用的乐器作映射:
[java] view plain copy
 print?
  1. private Map<String,String> musicians = new HashMap<String, String>();  
  2. public Map<String, String> getMusicians() {  
  3.         return Collections.unmodifiableMap(musicians);  
  4. }  
  5. public void addMusician(String key, String value){  
  6.         musicians.put(key, value);  
  7. }  

然后在main方法中加入:

[java] view plain copy
 print?
  1. album.addMusician("Miles Davis""Trumpet, Band leader");  
  2. album.addMusician("Julian Adderley""Alto Saxophone");  
  3. album.addMusician("Paul Chambers""double bass");  

JSON现在长这样:

[java] view plain copy
 print?
  1. {  
  2.   "title" : "Kind Of Blue",  
  3.   "links" : [ "link1""link2" ],  
  4.   "songs" : [ "So What""Flamenco Sketches""Freddie Freeloader" ],  
  5.   "artist" : {  
  6.     "name" : "Miles Davis",  
  7.     "birthDate" : -1376027600000  
  8.   },  
  9.   "musicians" : {  
  10.     "Julian Adderley" : "Alto Saxophone",  
  11.     "Paul Chambers" : "double bass",  
  12.     "Miles Davis" : "Trumpet, Band leader"  
  13.   }  
  14. }  

现在让我们来为这个转换加入更多新特性,首先我们要让mapper用它自带的方法来让Map依据键有序排列:

[java] view plain copy
 print?
  1. mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);  
然后我们把用新历显示的date变成更易于人类阅读的形式:
[java] view plain copy
 print?
  1. SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");  
  2. mapper.setDateFormat(outputFormat);  
默认情况下,jackson使用JAVA字段名作为JSON属性名,你能通过注解改变它正如在this课程中解释的那样,但是有时候你可能不能取得java bean或者你不想为它绑定注解,在这种情况下,jackson提供了一个方法来改变默认的字段名,调用mapper的setPropertyNamingStrategy来设置字段的命名策略,你必须重载nameForField方法或者nameForGetterMethod方法,这由你的java bean是public字段还是定义了getter来决定,在我们的例子中我们来将Album的title改为Album-Title,Artist的name改为Artist-Name,在main方法中完成这个改变。
[java] view plain copy
 print?
  1. mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {  
  2. @Override  
  3. public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {  
  4.    if (field.getFullName().equals("com.studytrails.json.jackson.Artist#name"))  
  5.         return "Artist-Name";  
  6.         return super.nameForField(config, field, defaultName);  
  7. }  
  8.    
  9. @Override  
  10. public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {  
  11.   if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))  
  12.         return "Album-Title";  
  13.         return super.nameForGetterMethod(config, method, defaultName);  
  14.   }  
  15. });  
现在让我们来看看jackson怎么处理空值,我们为Artist类增加以下三个新属性并且不为他们分配值:
[java] view plain copy
 print?
  1. public int age;  
  2. public String homeTown;  
  3. public List<String> awardsWon = new ArrayList<String>();  
当它们被转为JSON时,是这个样子:
[java] view plain copy
 print?
  1. "age" : 0,  
  2.  "homeTown" : null,  
  3.  "awardsWon" : [ ]  
我们用这个设置来忽略值为空的属性:
[java] view plain copy
 print?
  1. mapper.setSerializationInclusion(Include.NON_EMPTY);  
忽略空属性的确切过滤器的描述在this课程。
下面是完整的例子:
[java] view plain copy
 print?
  1. package com.studytrails.json.jackson;  
  2.    
  3. import java.io.IOException;  
  4. import java.text.ParseException;  
  5. import java.text.SimpleDateFormat;  
  6. import java.util.ArrayList;  
  7. import java.util.Collections;  
  8. import java.util.Date;  
  9. import java.util.HashMap;  
  10. import java.util.List;  
  11. import java.util.Map;  
  12.    
  13. import com.fasterxml.jackson.annotation.JsonInclude.Include;  
  14. import com.fasterxml.jackson.databind.ObjectMapper;  
  15. import com.fasterxml.jackson.databind.PropertyNamingStrategy;  
  16. import com.fasterxml.jackson.databind.SerializationFeature;  
  17. import com.fasterxml.jackson.databind.cfg.MapperConfig;  
  18. import com.fasterxml.jackson.databind.introspect.AnnotatedField;  
  19. import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;  
  20.    
  21. public class SerializationExample {  
  22.    
  23.     public static void main(String[] args) throws IOException, ParseException {  
  24.         ObjectMapper mapper = new ObjectMapper();  
  25.         Album album = new Album("Kind Of Blue");  
  26.         album.setLinks(new String[] { "link1""link2" });  
  27.         List<string> songs = new ArrayList<string>();  
  28.         songs.add("So What");  
  29.         songs.add("Flamenco Sketches");  
  30.         songs.add("Freddie Freeloader");  
  31.         album.setSongs(songs);  
  32.         Artist artist = new Artist();  
  33.         artist.name = "Miles Davis";  
  34.         SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");  
  35.         artist.birthDate = format.parse("26-05-1926");  
  36.         album.setArtist(artist);  
  37.         album.addMusician("Miles Davis""Trumpet, Band leader");  
  38.         album.addMusician("Julian Adderley""Alto Saxophone");  
  39.         album.addMusician("Paul Chambers""double bass");  
  40.         mapper.configure(SerializationFeature.INDENT_OUTPUT, true);  
  41.         mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);  
  42.         SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");  
  43.         mapper.setDateFormat(outputFormat);  
  44.         mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {  
  45.             @Override  
  46.             public String nameForField(MapperConfig<!--?--> config, AnnotatedField field, String defaultName) {  
  47.                 if (field.getFullName().equals("com.studytrails.json.jackson.Artist#name"))  
  48.                     return "Artist-Name";  
  49.                 return super.nameForField(config, field, defaultName);  
  50.             }  
  51.    
  52.             @Override  
  53.             public String nameForGetterMethod(MapperConfig<!--?--> config, AnnotatedMethod method, String defaultName) {  
  54.                 if (method.getAnnotated().getDeclaringClass().equals(Album.class) && defaultName.equals("title"))  
  55.                     return "Album-Title";  
  56.                 return super.nameForGetterMethod(config, method, defaultName);  
  57.             }  
  58.         });  
  59.         mapper.setSerializationInclusion(Include.NON_EMPTY);  
  60.         mapper.writeValue(System.out, album);  
  61.     }  
  62. }  
  63.    
  64. class Album {  
  65.     private String title;  
  66.     private String[] links;  
  67.     private List<string> songs = new ArrayList<string>();  
  68.     private Artist artist;  
  69.     private Map<string ,="" string=""> musicians = new HashMap<string ,="" string="">();  
  70.    
  71.     public Album(String title) {  
  72.         this.title = title;  
  73.     }  
  74.    
  75.     public String getTitle() {  
  76.         return title;  
  77.     }  
  78.    
  79.     public void setLinks(String[] links) {  
  80.         this.links = links;  
  81.     }  
  82.    
  83.     public String[] getLinks() {  
  84.         return links;  
  85.     }  
  86.    
  87.     public void setSongs(List<string> songs) {  
  88.         this.songs = songs;  
  89.     }  
  90.    
  91.     public List<string> getSongs() {  
  92.         return songs;  
  93.     }  
  94.    
  95.     public void setArtist(Artist artist) {  
  96.         this.artist = artist;  
  97.     }  
  98.    
  99.     public Artist getArtist() {  
  100.         return artist;  
  101.     }  
  102.    
  103.     public Map<string ,="" string=""> getMusicians() {  
  104.         return Collections.unmodifiableMap(musicians);  
  105.     }  
  106.    
  107.     public void addMusician(String key, String value) {  
  108.         musicians.put(key, value);  
  109.     }  
  110. }  
  111.    
  112. class Artist {  
  113.     public String name;  
  114.     public Date birthDate;  
  115.     public int age;  
  116.     public String homeTown;  
  117.     public List<string> awardsWon = new ArrayList<string>();  
  118. }  

这是第一部分,关于如何将JAVA对象转换为JSON。





第二部分将讲解如何通过树来创建JSON。

Jackson - Creating JSON Using a TreeModel


通过一个简单的树模型来创建JSON也是可以的,当你不想为你的JSON创建许多类时,这个方法非常有用。我们将使用上面那个例子,一个包含了songs数组、artist对象和musicians数组的,为了创建一个树你首先需要:
  • 创建一个JsonNodeFactory来创建节点
  • 通过JsonFactory创建一个JsonGenerator并且指定输出方法。在这个例子中我们输出到console
  • 它将使用jsonGenerator和树的根节点来创建JSON

完成上述步骤后我们为album创建一个单独的根节点,注意默认情况下mapper不会为这个根节点命名。

[java] view plain copy
 print?
  1. package com.studytrails.json.jackson;  
  2.    
  3. import java.io.IOException;  
  4.    
  5. import com.fasterxml.jackson.core.JsonFactory;  
  6. import com.fasterxml.jackson.core.JsonGenerator;  
  7. import com.fasterxml.jackson.databind.JsonNode;  
  8. import com.fasterxml.jackson.databind.ObjectMapper;  
  9. import com.fasterxml.jackson.databind.node.JsonNodeFactory;  
  10.    
  11. public class SerializationExampleTreeModel {  
  12.     public static void main(String[] args) throws IOException {  
  13.         // Create the node factory that gives us nodes.  
  14.         JsonNodeFactory factory = new JsonNodeFactory(false);  
  15.    
  16.         // create a json factory to write the treenode as json. for the example  
  17.         // we just write to console  
  18.         JsonFactory jsonFactory = new JsonFactory();  
  19.         JsonGenerator generator = jsonFactory.createGenerator(System.out);  
  20.         ObjectMapper mapper = new ObjectMapper();  
  21.    
  22.         // the root node - album  
  23.         JsonNode album = factory.objectNode();  
  24.         mapper.writeTree(generator, album);  
  25.    
  26.     }  
  27.    
  28. }  

This prints

{}
这么一大堆代码只是输出了一对符号!但是,现在才是看看怎么创建我们自己的json的时候,我们首先加入我们的第一个属性'Album-Title'.

[java] view plain copy
 print?
  1. album.put("Album-Title""Kind Of Blue");  
现在我们的JSON长这样:

{"Album-Title":"Kind Of Blue"}
现在我们加上links数组
[java] view plain copy
 print?
  1. ArrayNode links = factory.arrayNode();  
  2. links.add("link1").add("link2");  
  3. album.put("links", links);  
The JSON
{"Album-Title":"Kind Of Blue","links":["link1","link2"]}
下一步我们加上artist对象
[java] view plain copy
 print?
  1. ObjectNode artist = factory.objectNode();  
  2. artist.put("Artist-Name""Miles Davis");  
  3. artist.put("birthDate""26 May 1926");  
  4. album.put("artist", artist);  
The JSON
{"Album-Title":"Kind Of Blue","links":["link1","link2"],"artist":{"Artist-Name":"Miles Davis","birthDate":"26 May 1926"}}
现在我们加入musicians
[java] view plain copy
 print?
  1. ObjectNode musicians = factory.objectNode();  
  2. musicians.put("Julian Adderley""Alto Saxophone");  
  3. musicians.put("Miles Davis""Trumpet, Band leader");  
  4. album.put("musicians", musicians);  
The 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"}}
类似的你可以加入其它元素,如果你拥有许多个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。
[java] view plain copy
 print?
  1. //首先我们需要一个根节点,这里使用的是构造器,但我查api的时候发现JsonNodeFactory有一个instance字段,是全局唯一的,也就是单例的,不知道该用哪个,有待高人解//答  
  2. JsonNodeFactory factory = new JsonNodeFactory(false);  
  3. JsonNode album = factory.objectNode();  
  4. //然后创建一个JsonGenerator对象  
  5. JsonGeneratory generator = new JsonFactory().createGenerator(System.out);  
  6. //创建JsonNode节点  
  7.   
  8. ObjectNode artist = factory.objectNode();  
  9. artist.put("Artist-Name""Miles Davis");  
  10. artist.put("birthDate""26 May 1926");  
  11.   
  12. //把节点加到album上去  
  13.   
  14. album.put("artist", artist);  
  15.   
  16. //通过树模型生成JSON  
  17. ObjectMapper mapper = new ObjectMapper();  
  18. mapper.writeTree(generator,album);  

顺便附赠一下Jackson的jar包:http://pan.baidu.com/s/1sjnxJHF
0 0
原创粉丝点击