在Java平台(StAX, JAXB等)XML处理质量和多样化的激励下,Jackson为多功能的Java JSON处理包其目标为集快捷、正确、轻量和符合人体工程学与一体。
本文将给出Jackson的功能概览。
JSON的三种处理方式
Jackson提供了三种可选的JSON处理方法(一种方式及其两个变型):
-
流式 API:(也称为"增量分析/生成") 读取和写入 JSON 内容作为离散事件。
-
org.codehaus.jackson.JsonParser 读, org.codehaus.jackson.JsonGenerator 写。
-
StAX API 的激励。
-
-
树模型 :提供一个 JSON 文档可变内存树的表示形式。
-
org.codehaus.jackson.map.ObjectMapper 生成树 ;树组成 JsonNode 节点集。
- 树模型类似于 XML DOM。
-
-
数据绑定: JSON和POJO相互转换,基于属性访问器规约或注解。
-
有 两种变体: 简单 和 完整 的数据绑定:
-
简单数据绑定: 是指从Java Map、List、String、Numbers、Boolean和空值进行转换
-
完整数据绑定 :是指从任何 Java bean 类型 (及上文所述的"简单"类型) 进行转换
-
org.codehaus.jackson.map.ObjectMapper 对两个变种,进行编组(marshalling )处理 (写入 JSON) 和反编组(unmarshalling ,读 JSON)。
-
JAXB激励下的基于注释的 (代码优先)变种。
-
从使用的角度来看,总结这些3 种方法的用法如下:
Jackson的 org.codehaus.jackson.map.ObjectMapper "只是"将JSON 数据映射为POJO 对象 。例如,给定 JSON 数据:
{
"name" : { "first" : "Joe", "last" : "Sixpack" },
"gender" : "MALE",
"verified" : false,
"userImage" : "Rm9vYmFyIQ=="
}
1.用两行代码把它变成一个用户实例:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
User user = mapper.readValue(new File("user.json"), User.class);
编组为JSON同样简单
mapper.writeValue(new File("user-modified.json"), user);
2.Map
Map<String,Object> userData = mapper.readValue(new File("user.json"), Map.class);
JSON Type | Java Type |
object | LinkedHashMap<String,Object> |
array | ArrayList<Object> |
string | String |
number(no fraction) | Integer, Long or BigInteger (smallest applicable) |
number (fraction) | BigDecimal |
true|false | boolean |
null | null |
泛型的数据绑定
除绑定到POJO和简单类型外,还有一个额外的变型:绑定到泛型(类型)容器。此时,由于所谓的类型擦除(Java采用向后兼容的方式实现泛型),需要进行特殊处理,以防止使用类似 Collection<String>.class(不被编译)。
所以,热想绑定数据岛Map<String,User>,方式如下:
Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });
其中TypeReference只需传入泛型类型即可(此时需要匿名内部类):重要部分为<Map<String,User>>,定义要绑定的数据类型。
若不如此(仅定义Map.class),其调用等价于绑定到 Map<?,?>(亦即 “untyped” Map),如前所述。
更新:1.3版的Jackson允许利用TypeFactory实现构造类型。
树模式示例
另一种从JSON获取对象方式是构造“树”,类似于XML的DOM树。Jackson构造树的方法利用JsonNode基类,其中包含公开的通常所需的读取访问方法,实际所用的节点类型为其子类;但子类型仅在修改树时需要。
JSON树可通过流式API或ObjectMapper方式读、写。
利用 ObjectMapper,方法如下:
1 ObjectMapper m = new ObjectMapper();
2 // can either use mapper.readTree(JsonParser), or bind to JsonNode
3 JsonNode rootNode = m.readValue(new File("user.json"), JsonNode.class);
4 // ensure that "last name" isn't "Xmler"; if is, change to "Jsoner"
5 JsonNode nameNode = rootNode.path("name");
6 String lastName = nameNode.path("last").getTextValue().
7 if ("xmler".equalsIgnoreCase(lastName)) {
8 ((ObjectNode)nameNode).put("last", "Jsoner");
9 }
10 // and write it out:
11 m.writeValue(new File("user-modified.json"), rootNode);
一、入门
Jackson中有个ObjectMapper类很是实用,用于Java对象与JSON的互换。
1、Java对象转换为JSON:
User user=new User(); //Java Object
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString(user); //返回字符串
//输出格式化后的字符串(有性能损耗)
mapper.defaultPrettyPrintingWriter().writeValueAsString(user);
mapper.writeValue(new File("c:\\user.json"), user); //指定文件写入
//设置序列化配置(全局),设置序列化时不输出空值.
sharedMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
2、JSON反序列化为Java对象:
ObjectMapper mapper = new ObjectMapper();
//解析器支持解析单引号
mapper.configure(Feature.ALLOW_SINGLE_QUOTES,true);
//解析器支持解析结束符
mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,true);
HashMap jsonMap = mapper.readValue(json,HashMap.class); //转换为HashMap对象
二、Jackson支持3种使用方式:
1、Data Binding:最方便使用.
(1)Full Data Binding:
- private static final String MODEL_BINDING = "{\"name\":\"name1\",\"type\":1}";
- public void fullDataBinding() throws Exception{
- ObjectMapper mapper = new ObjectMapper();
- Model user = mapper.readValue(MODEL_BINDING, Model.class);//readValue到一个实体类中.
- System.out.println(user.getName());
- System.out.println(user.getType());
- }
Model类:
- private static class Model{
- private String name;
- private int type;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getType() {
- return type;
- }
- public void setType(int type) {
- this.type = type;
- }
- }
(2)Raw Data Binding:
- /**
- Concrete Java types that Jackson will use for simple data binding are:
- JSON Type Java Type
- object LinkedHashMap<String,Object>
- array ArrayList<Object>
- string String
- number(no fraction) Integer, Long or BigInteger (smallest applicable)
- number(fraction) Double(configurable to use BigDecimal)
- true|false Boolean
- null null
- */
- public void rawDataBinding() throws Exception{
- ObjectMapper mapper = new ObjectMapper();
- HashMap map = mapper.readValue(MODEL_BINDING,HashMap.class);//readValue到一个原始数据类型.
- System.out.println(map.get("name"));
- System.out.println(map.get("type"));
- }
(3)generic Data Binding:
- private static final String GENERIC_BINDING = "{\"key1\":{\"name\":\"name2\",\"type\":2},\"key2\":{\"name\":\"name3\",\"type\":3}}";
- public void genericDataBinding() throws Exception{
- ObjectMapper mapper = new ObjectMapper();
- HashMap<String,Model> modelMap = mapper.readValue(GENERIC_BINDING,new TypeReference<HashMap<String,Model>>(){});//readValue到一个范型数据中.
- Model model = modelMap.get("key2");
- System.out.println(model.getName());
- System.out.println(model.getType());
- }
2、Tree Model:最灵活。
- private static final String TREE_MODEL_BINDING = "{\"treekey1\":\"treevalue1\",\"treekey2\":\"treevalue2\",\"children\":[{\"childkey1\":\"childkey1\"}]}";
- public void treeModelBinding() throws Exception{
- ObjectMapper mapper = new ObjectMapper();
- JsonNode rootNode = mapper.readTree(TREE_MODEL_BINDING);
- //path与get作用相同,但是当找不到该节点的时候,返回missing node而不是Null.
- String treekey2value = rootNode.path("treekey2").getTextValue();//
- System.out.println("treekey2value:" + treekey2value);
- JsonNode childrenNode = rootNode.path("children");
- String childkey1Value = childrenNode.get(0).path("childkey1").getTextValue();
- System.out.println("childkey1Value:"+childkey1Value);
- //创建根节点
- ObjectNode root = mapper.createObjectNode();
- //创建子节点1
- ObjectNode node1 = mapper.createObjectNode();
- node1.put("nodekey1",1);
- node1.put("nodekey2",2);
- //绑定子节点1
- root.put("child",node1);
- //数组节点
- ArrayNode arrayNode = mapper.createArrayNode();
- arrayNode.add(node1);
- arrayNode.add(1);
- //绑定数组节点
- root.put("arraynode", arrayNode);
- //JSON读到树节点
- JsonNode valueToTreeNode = mapper.valueToTree(TREE_MODEL_BINDING);
- //绑定JSON节点
- root.put("valuetotreenode",valueToTreeNode);
- //JSON绑定到JSON节点对象
- JsonNode bindJsonNode = mapper.readValue(GENERIC_BINDING, JsonNode.class);//绑定JSON到JSON节点对象.
- //绑定JSON节点
- root.put("bindJsonNode",bindJsonNode);
- System.out.println(mapper.writeValueAsString(root));
- }
3、Streaming API:最佳性能。
见官方文档例子。
参考资料:
1、http://wiki.fasterxml.com/JacksonInFiveMinutes Jackson官方教程示例
2、http://wiki.fasterxml.com/JacksonJavaDocs Jackson在线API文档
3、http://hjg1988.iteye.com/blog/561368 JSON工具性能比较:json-lib和jackson进行Java对象到json字符串序列化。