Android Jackson 概述
本文内容
- JSON 的三种方式
- 示例
- 完全数据绑定(POJO)示例
- “Raw”数据绑定示例
- 用泛型数据绑定
- 树模型(Tree Model)示例
- 流(Streaming)API 示例
- 流(Streaming)API 示例 2:数组
- 演示代码
- 参考资料
- 术语
最近写 Android APP,需要序列化和反序列化。但是遇到一些问题,于是就顺便研究了一下 Jackson。因为,我是搞 .NET 的,怎么感觉比 Newtonsoft 要麻烦呢。如果不是因为麻烦,那就是因为 Jackson 实在太灵活了。
Jackson 是基于各种各样的 Java 平台(StAX,JAXB, 等等)上 XML 工具,一个用于处理 JSON 多用途的 Java 库。Jackson 的目标是对 Java 开发者来说最大可能的结合快速的、准确的、轻量级的和符合人体工程学。
本文使用 jackson-all-1.9.11 简单描述 Jackson 的功能。
下载 Demo
下载 jackson-all-1.9.11
JSON 的三种方式
Jackson 为处理 JSON 提供三种可选的方法(其中的一个有两个变体):
- Streaming API(又称“增量解析/生成”)把读写 JSON 内容作为离散事件。
- 用 org.codehaus.jackson.JsonParser 读,用 org.codehaus.jackson.JsonGenerator 写。
- 基于 StAX API。
- 树模型(Tree Model)提供了一个表示 JSON 文档的可变内存树。
- org.codehaus.jackson.map.ObjectMapper 可以生成树;树由 JsonNode 节点组成。
- 树模型类似 XML DOM。
- 数据绑定(Data Binding)把 JSON 和 基于属性访问器(property accessor)或注释的 POJO 之间进行转换。
- 有两个变体:简单数据绑定和完全数据绑定
- 简单数据绑定,意思是从或到 Java Map、List、String、Number、Boolean 和 null 的转换
- 完整数据绑定,意思是从或到任何 Java bean 类型(以及上面提到的“简单”类型)的转换
- org.codehaus.jackson.map.ObjectMapper 完成重排(marshalling/unmarshalling,对数据存储结构的重新编排转换,而不是数据结构),包括把对象写成 JSON,或读取 JSON 转换成对象
- 基于基于注解(代码优先)变种的 JAXB。
- 有两个变体:简单数据绑定和完全数据绑定
从使用的角度,这三种方式:
- 流 API,具有最好的性能(最低的开销,最快的读写;其他两个都是基于它的)
- 数据绑定,通常最方便
- 树模型,最灵活
对于这些特性,考虑倒着介绍,先从平时最自然、最方便的方法开始:Jackson 数据绑定 API。
示例
完全数据绑定(POJO)示例
org.codehaus.jackson.map.ObjectMapper 用于将 JSON 数据映射成普通的 Java 对象(plain old Java objects,POJOs)。因此,“完全数据绑定(POJO)”就是将 JSON 内容完整地映射成 Java 对象,它们一一对应。这是最简单的情况。例如,对于给定的 JSON 数据:
{
"name": {
"first": "Joe",
"last": "Sixpack"
},
"gender": "MALE",
"verified": false,
"userImage": "Rm9vYmFyIQ=="
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
用两行 Java 代码就可以把它转换成一个 User 实例:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
User user = mapper.readValue(new File("user.json"), User.class);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
User 类的定义如下所示:
public class User {
public enum Gender {
MALE, FEMALE
};
public static class Name {
private String _first, _last;
public String getFirst() {
return _first;
}
public String getLast() {
return _last;
}
public void setFirst(String s) {
_first = s;
}
public void setLast(String s) {
_last = s;
}
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() {
return _name;
}
public boolean isVerified() {
return _isVerified;
}
public Gender getGender() {
return _gender;
}
public byte[] getUserImage() {
return _userImage;
}
public void setName(Name n) {
_name = n;
}
public void setVerified(boolean b) {
_isVerified = b;
}
public void setGender(Gender g) {
_gender = g;
}
public void setUserImage(byte[] b) {
_userImage = b;
}
public String toString() {
return "name=" + this._name._last + " " + this._name._first
+ ",gender=" + this._gender;
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
把 User 对象再转换成 JSON,并保存名为 user-modified.json 文件,如下所示:
mapper.writeValue(new File("user-modified.json"), user);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
对于某些数据绑定(例如,把格式化的日期编排成 java.util.Date),Jackson 提供注解自定义重排的处理。
完全数据绑定是最简单的情况。我们很容易想到,一个是 Java 系统,另一个是 .net 系统,显然它们的类结构会不同(除非当初设计好了),即便不是两个不同框架,就算是一个框架下的不同子系统,要让这它们通信,一个系统序列化的 JSON,另一个系统反序列化 JSON 时完全不知道是什么。最好的办法当然是,在序列化时做点手脚,直接序列化成另一个系统能识别的 JSON。千万不能将序列化/反序列化理解得太狭隘,不是会调用序列化/反序列化两个函数就完事啦~
“Raw”数据绑定示例
(也称为“非类型”,或有时称为“简单”数据绑定)
在一些情况,我们没有明确的 Java 类(也不想这么做)去绑定 JSON,那么“非类型的数据绑定”是最好的方法。它的使用与完全数据绑定一样,只是简单地规定把 Object.class(或是 Map.class,List.class,String[].class 等)作为绑定类型。因此,User 的 JSON 绑定如下所示:
Map<String, Object> userData = mapper.readValue(new File("user.json"),
Map.class);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
userData 可以如下面代码显示构造:
Map<String, Object> userData = new HashMap<String, Object>();
Map<String, String> nameStruct = new HashMap<String, String>();
nameStruct.put("first", "Joe");
nameStruct.put("last", "Sixpack");
userData.put("name", nameStruct);
userData.put("gender", "MALE");
userData.put("verified", Boolean.FALSE);
userData.put("userImage", "Rm9vYmFyIQ==");
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如果你构造一个 Map,如上所示,或从 JSON 构造,并可能进行修改,那么你可以跟之前一样写成 JSON 文件:
mapper.writeValue(new File("user-modified-map.json"), userData);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Jackson 用于简单数据绑定的具体 Java 类型:
JSON Type | Java Type |
object | LinkedHashMap<String,Object> |
array | ArrayList |
string | String |
number(非小数) | Integer, Long 或 BigInteger (smallest applicable) |
number(小数) | Double (configurable to use BigDecimal) |
true|false | Boolean |
null | null |
用泛型数据绑定
除了绑定 POJOs 和“简单”类型外,还可以绑定泛型。
这种情况需要特殊处理,这是由于所谓的类型擦除(Type Erasure)(Java 以向后兼容的方式实现泛型),这会阻止你使用类似 Collection<String>.class (它不会被编译)。
因此,如果你想绑定数据到 Map<String,User>,你需要使用:
Map<String, User> userData = mapper.readValue(new File(
"user-modified-generic.json"),
new TypeReference<Map<String, User>>() {
});
其中,只能通过 TypeReference 传递泛型定义(在这种情况下,是通过 anynomous 内部类):最重要的部分是 <Map<String,User>>,它定义绑定到的类型。
如果你不这样做,而只是使用 Map.class,那么调用等价于绑定到 Map<?,?>(例如,"untyped" Map),正如前面说明的。
注意:作为替代方案,1.3 版本还允许通过 TypeFactory 构造。
树模型(Tree Model)示例
另一种从 JSON 获得对象的方式是建立一棵树。这类似 XML 的 DOM 树。Jackson 生成树的方式是使用基本的 JsonNode 基类,它公开了通常需要的读取访问。实际使用的节点类型是其子类;但子类只是在需要修改树时使用。
可以用 Streaming API (如下面小节)或是 ObjectMapper 来读/写树。
若用 ObjectMapper,则可以像下面的代码那样:
ObjectMapper mapper = new ObjectMapper();
// can either use mapper.readTree(source), or mapper.readValue(source,
// JsonNode.class);
JsonNode rootNode = mapper.readTree(new File("user.json"));
// ensure that "last name" isn't "Xmler"; if is, change to "Jsoner"
JsonNode nameNode = rootNode.path("name");
String lastName = nameNode.path("last").getTextValue();
if ("xmler".equalsIgnoreCase(lastName)) {
((ObjectNode) nameNode).put("last", "Jsoner");
}
// and write it out:
mapper.writeValue(new File("user-modified-tree.json"), rootNode);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
或者,你想用 User 示例从头构造一个树,你可以这样:
TreeMapper treeMapper = new TreeMapper();
ObjectNode userOb = treeMapper.objectNode();
Object nameOb = userRoot.putObject("name");
nameOb.put("first", "Joe");
nameOb.put("last", "Sixpack");
userOb.put("gender", User.Gender.MALE.toString());
userOb.put("verified", false);
byte[] imageData = getImageData(); // or wherever it comes from
userOb.put("userImage", imageData);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
注意:对于 Jackson 1.2,你可以直接使用 ObjectMapper,通过使用 ObjectMapper.createObjectNode() 来创建 userOb——以上代码是针对 Jackson 1.0 和 1.1)。
Streaming API 示例
最后,第三种方式:高性能的流 API(又称“增量模式”,因为可以增量地读写内容)。
JsonFactory f = new JsonFactory();
JsonGenerator g = f.createJsonGenerator(new File("user-stream.json"),
JsonEncoding.UTF8);
g.writeStartObject();
g.writeObjectFieldStart("name");
g.writeStringField("first", "Joe");
g.writeStringField("last", "Sixpack");
g.writeEndObject(); // for field 'name'
g.writeStringField("gender", Gender.MALE.toString());
g.writeBooleanField("verified", false);
g.writeFieldName("userImage"); // no 'writeBinaryField' (yet?)
byte[] binaryData = "Rm9vYmFyIQ==".getBytes();
g.writeBinary(binaryData);
g.writeEndObject();
// important: will force flushing of output, close underlying output
// stream
g.close();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
看上去也不是特别糟糕(特别是,与需要写的工作量相比,可以说,相当于 XML 内容),但肯定比基本对象映射费劲点。
在另一方面,你也可以完全控制每个细节。开销最小:这比使用 ObjectMapper 要快一点;通常情况快 20-30%。但或许最重要的是,已流的方式输出:除了一些缓冲,所有内容会将立刻写出来。这意味着,内存的使用也是最小的。
那么如何解析?如下代码所示:
JsonFactory f = new JsonFactory();
JsonParser jp = f.createJsonParser(new File("user.json"));
User user = new User();
jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jp.getCurrentName();
jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
if ("name".equals(fieldname)) { // contains an object
Name name = new Name();
while (jp.nextToken() != JsonToken.END_OBJECT) {
String namefield = jp.getCurrentName();
jp.nextToken(); // move to value
if ("first".equals(namefield)) {
name.setFirst(jp.getText());
} else if ("last".equals(namefield)) {
name.setLast(jp.getText());
} else {
throw new IllegalStateException("Unrecognized field '"
+ fieldname + "'!");
}
}
user.setName(name);
} else if ("gender".equals(fieldname)) {
user.setGender(User.Gender.valueOf(jp.getText()));
} else if ("verified".equals(fieldname)) {
user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
} else if ("userImage".equals(fieldname)) {
user.setUserImage(jp.getBinaryValue());
} else {
throw new IllegalStateException("Unrecognized field '"
+ fieldname + "'!");
}
}
// ensure resources get cleaned up timely and properly
jp.close();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
最后,可能直接利用 JsonParser 和 JsonGenerator 进行数据绑定和树模型。你可以看下下面方法:
- JsonParser.readValueAs()
- JsonParser.readValueAsTree()
- JsonGenerator.writeObject()
- JsonGenerator.writeTree()
你必须使用 org.codehaus.jackson.map.MappingJsonFactory 来构造解析器和生成器,而不是 org.codehaus.jackson.JsonFactory。
Streaming API 示例 2:数组
考虑下面的 POJO:
public class Foo {
public String foo;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
以及 JSON 流:
String json = [{\"foo\": \"bar\"},{\"foo\": \"biz\"}]";
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
有一个便利的方式进行这种数据绑定(参看 ObjectReader.readValues()),你可以很容易地使用流来迭代,以及绑定单个元素:
JsonFactory f = new JsonFactory();
JsonParser jp = f.createJsonParser(json);
// advance stream to START_ARRAY first:
jp.nextToken();
// and then each time, advance to opening START_OBJECT
while (jp.nextToken() == JsonToken.START_OBJECT)) {
Foo foobar = mapper.readValue(jp, Foo.class);
// process
// after binding, stream points to closing END_OBJECT
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
演示代码
- Windows 7 64 位
- Eclipse ADT V22.6.2
图 1 项目结构
- com.example.jacksondemo 包,是主程序;
- com.example.jacksondemo.studemo 包,是针对 Student 实体的定义及其测试类;
- com.example.jacksondemo.userdemo 包,是针对 User 实体的定义及其测试类,也是本文的演示代码;
- com.example.jacksondemo.catedemo 包,是针对网上一个大的 JSON 文件的定义及其测试类;
- com.example.jacksondemo.advanced 和 com.example.jacksondemo.junit 包,提了一下,Jackson 的高级用法及其单元测试类。具体请看“参考资料”小节;
- *.json 文件是本演示所生成,用于序列化和反序列化。
参考资料
- Jackson – JsonMappingException (No serializer found for class)
- Jackson JSON Tutorial
- Jackson 官网
- Jackson Download
- Android 基本 Jackson Marshalling(serialize)/Unmarshalling(deserialize)
术语
JAXB
JAXB(Java Architecture for XML Binding)是一个业界的标准,是一项可以根据 XML Schema 产生 Java 类的技术。JAXB 2.0 是 JDK 1.6 的组成部分。JAXB 2.2.3 是JDK 1.7 的组成部分。JAXB 能够使用 Jackson 对 JAXB 注解的支持实现(jackson-module-jaxb-annotations),既方便生成 XML,也方便生成 JSON。常用的注解包括:@XmlRootElement、@XmlElement 等等。
JAXB 提供了将XML 实例文档反向生成 Java 对象树的方法,并能将 Java 对象树的内容重新写到 XML 实例文档。另一方面,JAXB 提供了快速而简便的方法将 XML 模式绑定到 Java 表示,从而使 Java 开发者在 Java 应用程序中能方便地结合 XML 数据和处理函数。
StAX
StAX 是 Streaming API for XML 的缩写,是一种针对 XML 的流式拉分析 API。StAX 是一种面向流的新方法,最终版本于 2004 年 3 月发布,并成为 JAXP 1.4(Java 6.0 中)的一部分。StAX 的实现使用了 JWSDP(Java Web Services Development Pack)1.6,并结合了 SJSXP(Sun Java System XML Streaming Parser)。
XML 进行解析技术,在 Java 6.0 之前,就已经有四种:
- DOM - Document Object Model
- SAX - Simple API for XML
- JDOM - Java-based Document Object Model
- DOM4J - Document Object Model for Java
在程序中访问和操作 XML 文件一般有两种模型:DOM 和流模型。
- DOM 的优点是,允许编辑和更新 XML 文档,随机访问文档中的数据,使用 XPath(XML Path Language)查询;而缺点是,需要一次性把整个文档加载到内存中,对于大型文档,会造成性能问题。
- 流模型的优点是,对访问 XML 文件采用流的概念,在任何时候内存中只有当前节点,解决了 DOM 性能问题;但缺点是,只读且只能向前,不能在文档中执行向后操作。
流模型每次迭代 XML 文档中的一个节点,适合于处理较大的文档,内存消耗小。它有两种变体:“推”模型和“拉”模型。
- 推模型,就是我们常说的 SAX,它是一种事件驱动模型。每发现一个节点就触发一个事件,而我们需要编写这些事件的处理程序。这样的做法很麻烦,且不灵活。
- 拉模型,在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。
下载 Demo
下载 jackson-all-1.9.11
Android Jackson 概述的更多相关文章
- [Learn Android Studio 汉化教程]第二章:Android Studio概述(一)
[Learn Android Studio ]第二章:Android Studio概述(一) Android Studio是一个视窗化的开发环境.为了充分利用有限的屏幕空间,不让你束手束脚,Andro ...
- Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护
Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称password学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文.而解密则是通过解密 ...
- android视图概述
android视图概述 一.简介 数据和控件分开的作用: 便于引用 便于修改:修改的时候直接改一次数据就可以了
- Android零基础入门第33节:Android事件处理概述
原文:Android零基础入门第33节:Android事件处理概述 通过对Android基本组件的学习,也有接触少部分Android的事件处理,比如按钮的点击事件.选框的状态切换事件. 一.Andro ...
- android view : 概述
关于view的显示和绘制,不会去了解底层,仅仅在framework层做一些概述:以oo的思想,那么窗口的显示,内容的显示一定都有对应的类来相对应.了解了这一点之后,就去抽象一下android为了显示窗 ...
- Android核心分析之十六Android电话系统-概述篇
Android电话系统之概述篇 首先抛开Android的一切概念来研究一下电话系统的最基本的描述.我们的手机首先用来打电话的,随后是需要一个电话本,随后是PIM,随后是网络应用,随后是云计算,随后是想 ...
- 第一部分 Android MediaPlayer 概述
[IT168 技术文档]本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.对于Android这样一个完整又相对复杂的系统,一个MediaPlayer功能 ...
- Android传感器概述-android学习之旅(七)
传感器概述 传感器是第二代智能手机的重要标志之一.现在许多的手机和平板都内置了传感器(tv除外).android的SDK支持许多的传感器有十几种,但是手机只是支持一部分.例如方向传感器(电子罗盘)和重 ...
- android:launchMode概述
android:launchMode An instruction on how the activity should be launched. There are four modes that ...
随机推荐
- RednaxelaFX:软件工程师、主攻高级编程语言虚拟机的设计与实现
https://www.zhihu.com/people/rednaxelafx/posts
- delphi GetKeyState
GetKeyState(VK_CAPITAL) & 0x0001 0x8000 是键有否按下0x0001 是键的翻转状态 var bF1Down: Boolean;begin bF1Down ...
- SAP BAPI一览 史上最全
全BADI一览 List of BAPI's BAPI WG Component Function module name Description Description Obj. Ty ...
- C#编程(四十三)----------Lambda表达式
Lambda表达式 案例: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- 如何修改Oracle Enterprise Linux时区?
修改/etc/sysconfig/clock [root@psdyy-2 ~]# cat /etc/sysconfig/clock ZONE="Asia/Shanghai" UTC ...
- Android4.1中BinderService的作用
http://blog.csdn.net/lsdmx2016/article/details/8772583 Android4.1 中出现了一个新的类,BinderService,所有的Native ...
- WordPress主题开发:加载脚本和样式
如果只引入style.css,我把这个放头顶就可以了 <link rel="stylesheet" href="<?php echo get_styleshe ...
- poj 3041(最大匹配问题)
http://poj.org/problem?id=3041 Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions ...
- 重载hash与isEqual:方法
重载hash与isEqual:方法 前言 NSObject 自带了hash与isEqual:方法,服务于具有hash表结构的数据结构.NSObject自带的hash函数相当于hash表中的f(key) ...
- 微服务中的 API 网关(API Gateway)
API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需进行 ...