`
wusuoya
  • 浏览: 643107 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

使用 Jackson 把 Java 对象转换成 JSON 字串

 
阅读更多

原来 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 基本语法(四)——字串和数组

    ### Java基本语法(四)—— 字串和数组 #### 字串(String) 在Java中,`String` 是一种非常重要的数据类型,它代表一系列字符。Java中的字符串是不可变的,这意味着一旦创建了一个字符串对象,其内容就不能更改。...

    JSON模块修改版.rar

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它采用完全独立于语言的文本格式,但也使用了类似于C家族语言(包括C、C++、C#、Java、JavaScript、Perl、Python等)的习惯,这使得JSON成为理想的...

    JSON解析模块2.0.rar

    在易语言中,JSON解析模块2.0提供了对JSON数据的读取、写入和操作功能,使得开发者能够方便地将JSON格式的数据转换为易语言的数据结构,或者将易语言的数据结构转换为JSON字符串,以便于在网络上传输或存储。...

    Python-biglistofnaughtystrings淘气字串大列表收集了用户输入时经常出错的字串包含py脚本和JSON格式数据

    《Python淘气字串大列表:理解和应对用户输入异常》 在编程中,尤其是在与用户交互的场景下,处理用户输入是一项重要的任务。用户输入的数据可能会包含各种异常情况,如特殊字符、非法语法、编码问题等,这些异常...

    protobuf根据DebugString输出字串反解pb对象的实例(C++)

    使用过protobuf的同学肯定对pb的DebugString相关方法再熟悉不过了,其作用就是打印输出pb对象。有些时候我们可能会有根据这个输出还原原始pb对象的需求。仔细观察发现输出并不是标准json格式,也就是说基于json→pb...

    android字串的拆分问题

    例如,读取JSON文件时,我们可能会先用 `BufferedReader` 或 `InputStreamReader` 读取整个文件内容成字符串,再用 `Gson` 或 `Jackson` 库的解析方法来拆分和解析JSON字符串。 总之,理解并熟练掌握Android中字符...

    正则表达式 Java 判断字串是否合理

    根据给定的文件信息,我们可以总结出以下关于Java正则表达式的重要知识点: ### 1. 正则表达式简介 正则表达式是一种强大的文本处理工具,它能够帮助我们匹配、查找、替换等操作符合某种规则的字符串。在Java中,...

    kifuparser:将将棋的棋谱(游戏记录)数据格式转换为JSON

    将kif,ki2和csa数据格式转换为JSON或JavaScript对象 JSON的Kifu格式 { 标头[对象] 日期[对象] 开始[字符串] 结束[字符串] 网站[字串] 差点[数字] 标题[string] 动作[个数] 事件[字符串] 开头[string] ...

    java中数据类型转换

    1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([String],[int radix]); 2). int i = Integer.valueOf(my_str).intValue(); 注: ...

    html转C语言字串或数组工具

    2. **字串转换**:将HTML元素及其属性转化为C语言字符串,方便在代码中直接引用或处理。 3. **数组生成**:将HTML内容转换为C语言数组,如字符数组或结构体数组,便于内存管理和操作。 4. **图片转换**:描述中提到...

    Android利用Gson解析嵌套多层的Json的简单方法

    总之,Android开发中利用Gson解析嵌套多层的JSON数据主要分为两个步骤:一是创建与JSON结构对应的Java Bean类,二是使用Gson的`fromJson()`方法将JSON字符串转化为Java对象。理解这一过程对于处理复杂数据交换至关...

    VB.NET 字符串与二进制间的转换

    当处理大量数据或文件时,使用`FileStream`、`MemoryStream`等流对象可以更高效。例如,你可以将字符串写入`MemoryStream`,然后用`MemoryStream.ToArray()`获取字节数组。 5. **XML 或 JSON 序列化** 如果你的...

    字串转换(源码)

    这里的“字串转换(源码)”是指实现特定功能的代码,它能够将原始字串(通常指的是ASCII或其他编码的字符串)转换成Unicode表示,并且反之亦然。Unicode是一种通用的字符编码标准,它为世界上几乎所有的字符分配了一...

    JAVA数据类型转换

    例如,`stringToInt`方法使用`Integer.valueOf()`将字符串转换为`Integer`对象,然后通过`intValue()`得到`int`值。其他方法如`stringToFloat`和`floatToString`遵循相同的概念。 总的来说,理解并正确使用Java中的...

    JavaScript对象和字串之间的转换实例探讨

    如果想要将对象转换成JSON格式的字符串,我们可以使用`JSON.stringify()`方法: ```javascript var obj = { attr1: 'value1', attr2: 'value2' }; var jsonString = JSON.stringify(obj); console.log(jsonString);...

    进制及字串转换

    进制及字串转换是计算机科学中的基础概念,它们在编程和数据处理中扮演着重要角色。本程序基于Dephi开发,集成了多种进制转换和字符串操作功能,旨在为用户提供方便的操作体验。 首先,我们要了解什么是进制。进制...

    SqlServer将查询结果转换为XML和JSON

    在这个例子中,`@ParameterSQL`变量包含了你要执行的SQL查询,`FOR XML RAW, TYPE, ELEMENTS`是用于生成XML的选项,`sp_executesql`执行SQL并把结果赋值给`@XML`,最后将XML对象转换为字符串。 2. 查询结果转JSON ...

    JSON-handle

    JSON-handle是一款对JSON格式的内容进行浏览和编辑,以树形图样式展现JSON文档,并可实时编辑,美化整个JSON字串,使JSON结构一目了然,还能对JSON中的对象进行展开及收起,可以大大提升开发效率 。

    Thinking in Java 中文第四版+习题答案

    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毕业设计文献翻译

    句柄实际是指向一个对象的“句柄”,可以将其想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。 在Java中,所有对象都必须创建。创建句柄时,我们希望它同一个新...

Global site tag (gtag.js) - Google Analytics