原来 Java 项目中用的 JSON 组件库主要是 Gson 和 json-lib,Gson 算是很错的库,json-lib 略显寒碜。好啦,最近 Play 2.x 中弃用了 Gson 而采纳了 Jackson,所以现在就来打探一下 Jackson,踩个点吧。
Jackson 号称非常高的性能,听说比另两位兄弟 Gson 和 json-lib 高出一大截,我没有亲测,可是有心人做了,看这个链接 两款JSON类库Jackson与JSON-lib的性能对比(新增第三款测试) 中的数据。2010 年 8 月份的测试结果,不知现在随着版本的变更是否仍然保持着这种悬殊。
通常我会在把文章开头塞丰满,做足前戏,并不是因为在天涯混习惯了的缘故,况且我在天涯总是讷于言的; 在这里,自己的地盘自己作主,不会有要求码足多少字才能发表的自虐性需求,仅仅是让本文在主页上显示时的的概要不空洞而已,可以简单粗暴的称之为废话。
了了,先了解 Jacson 最贴近实际应用场景的应用,即 Jackson 怎么把一个 Java 生成对应的 JSON 字符串,看看前面的文字有这么多了,直接上一段代码吧,而后再慢慢假设与分解:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
package cc.unmi.testjackson;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
/** * @author Unmi
*/
public class TestClient {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true );
Person person = new Person( "Unmi" , new Address( "JiangXi" ));
String json = mapper.writeValueAsString(person);
System.out.println(json);
}
} class Person {
private String name;
private Address address;
public Person(String name, Address address){
this .name = name;
this .address = address;
}
} class Address {
private String province;
public Address(String province){
this .province = province;
}
public String getProvince(){
return this .province;
}
} |
要使用 Jackson,自然要引入相应的 jar 包,用 Maven 管理依赖的在 pom.xml 中加上:
1
2
3
4
5
|
< dependency >
< groupId >org.codehaus.jackson</ groupId >
< artifactId >jackson-mapper-asl</ artifactId >
< version >1.9.11</ version >
</ dependency >
|
这样在项目中就会有了 jackson-mapper-asl-1.9.11.jar 和 jackson-core-asl-1.9.11.jar 这两个 jar 包,其实当前版本是 2.1.0,只是 Maven 中央库中还没有。
上面代码结果是可预测了,就是:
1
2
3
4
5
6
|
{ "name" : "Unmi" ,
"address" : {
"province" : "JiangXi"
}
} |
Jackson 提供了 ObjectMapper 和 JsonGenerator 两个 API 让你去玩转 JSON,其实内部实现肯定汇合在一起了,别让两个选择就使你不会选择了。
如果把第一段代码中的第 20 行拿掉,运行会抛出异常:
Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: No serializer found for class cc.unmi.testjackson.Person and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) )
at org.codehaus.jackson.map.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:52)
at org.codehaus.jackson.map.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:25)
at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
原因是 Jackson 默认情况下不知道怎么去序列化,解决办法是:
1. 用上面的第 20 行代码,setVisibility,这个属性也可以通过 SerializationConfig 来设置
2. 或是给你要转换 Json 的类加上注解 @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)3. 也可以给字段或 getter 上加上 @JsonProperty 注解,还能用它指定序列化时的属性名
第 21 行是辅助设置,对格式的控制等,比要不要输出 null 值的,数字日期怎么显示,多瞧瞧那些 Feature:
org.codehaus.jackson.map.SerializationConfig.Feature.*
org.codehaus.jackson.JsonGenerator.Feature.*
org.codehaus.jackson.JsonParser.Feature.*
Jackson 的定制性还是很强的。再来想像这么一个需求,想输出的 JSON 属性也可定制,比如不想 {"name": "Unmi"},想要属性的第一个字母是大写的,{"Name": "Unmi"}。没问题,用 ObjectMapper 的
setPropertyNamingStrategy(PropertyNamingStrategy s) 方法
定义自己的 PropertyNamingStrategry, 可以继承自 PropertyNamingStrategy 或 PropertyNamingStrategyBase,显然继承自 PropertyNamingStrategyBase 来简单,因为它帮你适配了,只需覆写它的一个方法,如:
01
02
03
04
05
06
07
08
09
10
11
|
import org.codehaus.jackson.map.PropertyNamingStrategy.PropertyNamingStrategyBase;
public class CapitalizedPropertyNamingStrategy extends PropertyNamingStrategyBase {
@Override
public String translate(String propertyName) {
String name = propertyName.replaceAll( "^\\w" , propertyName.toUpperCase().substring( 0 , 1 ));
return name;
}
} |
然后对 mapper 调用
1
|
mapper.setPropertyNamingStrategy( new CapitalizedPropertyNamingStrategy());
|
再次运行代码,结果就变成了:
1
2
3
4
5
6
|
{ "Name" : "Unmi" ,
"Address" : {
"Province" : "JiangXi"
}
} |
还有什么需求,混迹代码中,最不能缺的就是想像力了。
小结一下:
1. ObjectMapper 可用来序列化和反序列化对象,而 JsonParser 是用来反序列化的,JsonGenerator 是序列化的。若想让代码职责分明,就用 JsonParser 或 JsonGenerator 代替 ObjectMapper 来用
2. ObjectMapper 和 JsonGenerator 有各种各样的 writeXxx() 方法,可以让结果输出到不同的目的地; 同样 ObjectMapper 和 JsonParser 也有各色 readXxx() 方法,方便你从不同的源获得数据
3. 多看看 Jackson 为我们提供了注释 Annotation,留意上面那几个 Feature 中有些什么枚举值,这里面也是我们的扩展点。
参考: 1. JacksonInFiveMinutes
相关推荐
### Java基本语法(四)—— 字串和数组 #### 字串(String) 在Java中,`String` 是一种非常重要的数据类型,它代表一系列字符。Java中的字符串是不可变的,这意味着一旦创建了一个字符串对象,其内容就不能更改。...
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它采用完全独立于语言的文本格式,但也使用了类似于C家族语言(包括C、C++、C#、Java、JavaScript、Perl、Python等)的习惯,这使得JSON成为理想的...
在易语言中,JSON解析模块2.0提供了对JSON数据的读取、写入和操作功能,使得开发者能够方便地将JSON格式的数据转换为易语言的数据结构,或者将易语言的数据结构转换为JSON字符串,以便于在网络上传输或存储。...
《Python淘气字串大列表:理解和应对用户输入异常》 在编程中,尤其是在与用户交互的场景下,处理用户输入是一项重要的任务。用户输入的数据可能会包含各种异常情况,如特殊字符、非法语法、编码问题等,这些异常...
使用过protobuf的同学肯定对pb的DebugString相关方法再熟悉不过了,其作用就是打印输出pb对象。有些时候我们可能会有根据这个输出还原原始pb对象的需求。仔细观察发现输出并不是标准json格式,也就是说基于json→pb...
例如,读取JSON文件时,我们可能会先用 `BufferedReader` 或 `InputStreamReader` 读取整个文件内容成字符串,再用 `Gson` 或 `Jackson` 库的解析方法来拆分和解析JSON字符串。 总之,理解并熟练掌握Android中字符...
根据给定的文件信息,我们可以总结出以下关于Java正则表达式的重要知识点: ### 1. 正则表达式简介 正则表达式是一种强大的文本处理工具,它能够帮助我们匹配、查找、替换等操作符合某种规则的字符串。在Java中,...
将kif,ki2和csa数据格式转换为JSON或JavaScript对象 JSON的Kifu格式 { 标头[对象] 日期[对象] 开始[字符串] 结束[字符串] 网站[字串] 差点[数字] 标题[string] 动作[个数] 事件[字符串] 开头[string] ...
1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([String],[int radix]); 2). int i = Integer.valueOf(my_str).intValue(); 注: ...
2. **字串转换**:将HTML元素及其属性转化为C语言字符串,方便在代码中直接引用或处理。 3. **数组生成**:将HTML内容转换为C语言数组,如字符数组或结构体数组,便于内存管理和操作。 4. **图片转换**:描述中提到...
总之,Android开发中利用Gson解析嵌套多层的JSON数据主要分为两个步骤:一是创建与JSON结构对应的Java Bean类,二是使用Gson的`fromJson()`方法将JSON字符串转化为Java对象。理解这一过程对于处理复杂数据交换至关...
当处理大量数据或文件时,使用`FileStream`、`MemoryStream`等流对象可以更高效。例如,你可以将字符串写入`MemoryStream`,然后用`MemoryStream.ToArray()`获取字节数组。 5. **XML 或 JSON 序列化** 如果你的...
这里的“字串转换(源码)”是指实现特定功能的代码,它能够将原始字串(通常指的是ASCII或其他编码的字符串)转换成Unicode表示,并且反之亦然。Unicode是一种通用的字符编码标准,它为世界上几乎所有的字符分配了一...
例如,`stringToInt`方法使用`Integer.valueOf()`将字符串转换为`Integer`对象,然后通过`intValue()`得到`int`值。其他方法如`stringToFloat`和`floatToString`遵循相同的概念。 总的来说,理解并正确使用Java中的...
如果想要将对象转换成JSON格式的字符串,我们可以使用`JSON.stringify()`方法: ```javascript var obj = { attr1: 'value1', attr2: 'value2' }; var jsonString = JSON.stringify(obj); console.log(jsonString);...
进制及字串转换是计算机科学中的基础概念,它们在编程和数据处理中扮演着重要角色。本程序基于Dephi开发,集成了多种进制转换和字符串操作功能,旨在为用户提供方便的操作体验。 首先,我们要了解什么是进制。进制...
在这个例子中,`@ParameterSQL`变量包含了你要执行的SQL查询,`FOR XML RAW, TYPE, ELEMENTS`是用于生成XML的选项,`sp_executesql`执行SQL并把结果赋值给`@XML`,最后将XML对象转换为字符串。 2. 查询结果转JSON ...
JSON-handle是一款对JSON格式的内容进行浏览和编辑,以树形图样式展现JSON文档,并可实时编辑,美化整个JSON字串,使JSON结构一目了然,还能对JSON中的对象进行展开及收起,可以大大提升开发效率 。
A.1.3 传递和使用Java对象 A.1.4 JNI和Java违例 A.1.5 JNI和线程处理 A.1.6 使用现成代码 A.2 微软的解决方案 A.3.1 @dll.import引导命令 A.3.2 com.ms.win32包 A.3.3 汇集 A.3.4 编写回调函数 A.3.5 其他J/Direct...
句柄实际是指向一个对象的“句柄”,可以将其想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。 在Java中,所有对象都必须创建。创建句柄时,我们希望它同一个新...