欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?

程序员文章站 2022-04-10 13:37:48
昨天下午 5 点 10 分左右,我解决掉了最后一个 bug,轻舒一口气,准备关机下班。可这个时候,老板朝我走来,脸上挂着神秘的微笑,我就知道他不怀好意。果不其然,他扔给了我一个新的需求,要我在 Java 中解析 JSON,并且要在半个小时候给出最佳的解决方案。 无奈,提前下班的希望破灭了。不过,按时 ......

昨天下午 5 点 10 分左右,我解决掉了最后一个 bug,轻舒一口气,准备关机下班。可这个时候,老板朝我走来,脸上挂着神秘的微笑,我就知道他不怀好意。果不其然,他扔给了我一个新的需求,要我在 java 中解析 json,并且要在半个小时候给出最佳的解决方案。

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?

无奈,提前下班的希望破灭了。不过,按时下班的希望还是有的。于是我撸起袖子开始了研究,结果出乎我的意料,竟然不到 10 分钟就找出了最佳方案。但我假装还没有搞出来,趁着下班前的这段时间把方案整理成了现在你们看到的这篇文章。

01、json 是什么

json(javascript object notation)是一种轻量级的数据交换格式,易于阅读和编写,机器解析和生成起来更是轻而易举。json 采用了完全独立于编程语言的文本格式,但它的格式非常符合 c 语言家族的习惯(比如 c、c++、c#、java、javascript、python 等)。 这种特质使得 json 成为了最理想的数据交换格式。

json 建构于两种常见的数据结构:

  • “键/值”对。
  • 数组。

这使得 json 在同样基于这些结构的编程语言之间的交换成为可能。在 java 中,解析 json 的第三方类库有很多,比如说下面这些。

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?

很多,对不对?但日常开发中,最常用的只有四个:gson、jackson、org.json 和阿里巴巴的 fastjson。下面我们来简单地对比下。

02、gson

gson 是谷歌提供的一个开源库,可以将 java 对象序列化为 json 字符串,同样可以将 json 字符串反序列化(解析)为匹配的 java 对象。

使用 gson 之前,需要先在项目中引入 gson 的依赖。

<dependency>
    <groupid>com.google.code.gson</groupid>
    <artifactid>gson</artifactid>
    <version>2.8.6</version>
    <scope>compile</scope>
</dependency>

1)简单示例

gson gson = new gson();
gson.tojson(18);            // ==> 18
gson.tojson("沉默王二");       // ==> "沉默王二"

上面这段代码通过 new 关键字创建了一个 gson 对象,然后调用其 tojson() 方法将整形和字符串转成了 json 字符串。

同样,可以调用 fromjson() 方法将简单的 json 字符串解析为整形和字符串。

int one = gson.fromjson("18", int.class);
integer one1 = gson.fromjson("18", integer.class);
string str = gson.fromjson("\"沉默王二\"", string.class);

2)复杂点的示例

cmower 类有两个字段:整形 age 和 字符串 name。

class cmower {
    private int age = 18;
    private string name = "沉默王二";
}

将其转成 json 字符串。

gson gson = new gson();
string json = gson.tojson(new cmower());
system.out.println(json);

输出结果为:

{"age":18,"name":"沉默王二"}

可以再通过 fromjson() 方法将字符串 json 解析为 java 对象。

gson.fromjson(json, cmower.class);

3)数组示例

gson gson = new gson();
int[] ints = {1, 2, 3, 4, 5};
string[] strings = {"沉", "默", "王二"};

// 转成 json 字符串
gson.tojson(ints);     // ==> [1,2,3,4,5]
gson.tojson(strings);  // ==> ["沉", "默", "王二"]

// 解析为数组
int[] ints2 = gson.fromjson("[1,2,3,4,5]", int[].class);
string[] strings2 = gson.fromjson("[\"沉\", \"默\", \"王二\"]", string[].class);

数组的处理仍然非常简单,调用的方法也仍然是 tojson()fromjson() 方法。

4)集合示例

gson gson = new gson();
list<string> list = new arraylist<>(arrays.aslist("沉", "默", "王二"));
string json = gson.tojson(list); // ==> ["沉","默","王二"]

把集合转成 json 字符串并没有什么特别之处,不过,把 json 字符串解析为集合就和之前的方法有些不同了。

type collectiontype = new typetoken<arraylist<string>>(){}.gettype();
list<string> list2 = gson.fromjson(json, collectiontype);

我们需要借助 com.google.gson.reflect.typetokenjava.lang.reflect.type 来获取集合的类型,再将其作为参数传递给 formjson() 方法,才能将 json 字符串解析为集合。

gson 虽然可以将任意的 java 对象转成 json 字符串,但将字符串解析为指定的集合类型时就需要花点心思了,因为涉及到了泛型——typetoken 是解决这个问题的银弹。

关于 gson,我们就先说到这吧,以后有机会的时候再和大家细说。

03、jackson

jackson 是基于 stream 构建的一款用来序列化和反序列化 json 的 java 开源库,社区非常活跃,其版本的更新速度也比较快。

  • 截止到目前,github 上已经星标 5.2k 了;
  • spring mvc 的默认 json 解析器;
  • 与 gson 相比,jackson 在解析大的 json 文件时速度更快。
  • 与 fastjson 相比,jackson 更稳定。

在使用 jackson 之前,需要先添加 jackson 的依赖。

<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-databind</artifactid>
    <version>2.9.1</version>
</dependency>

jackson 的核心模块由三部分组成。

  • jackson-core,核心包,提供基于"流模式"解析的相关 api,它包括 jsonpaser 和 jsongenerator。
  • jackson-annotations,注解包,提供标准注解功能。
  • jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 api ( objectmapper ) 和"树模型" 解析的相关 api (jsonnode);基于"对象绑定" 解析的 api 和"树模型"解析的 api 依赖基于"流模式"解析的 api。

当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 java 项目工程中。

这里顺带推荐一个 idea 插件:jsonformat,可以将 json 字符串生成一个 javabean。怎么使用呢?可以新建一个类,然后调出 generate 菜单。

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?

选择 jsonformat,输入 json 字符串。

{
  "age" : 18,
  "name" : "沉默王二"
}

确认后生成 javabean,生成的内容如下所示。

public class cmower {
    private integer age;
    private string name;

    public cmower() {
    }

    public cmower(integer age, string name) {
        this.age = age;
        this.name = name;
    }

    public integer getage() {
        return age;
    }

    public void setage(integer age) {
        this.age = age;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
    }
}

那怎么使用 jackson 呢?上文已经提到,objectmapper 是 jackson 最常用的 api,我们来看一个简单的示例。

cmower wanger = new cmower(18,"沉默王二");
system.out.println(wanger);

objectmapper mapper = new objectmapper();
string jsonstring = mapper.writerwithdefaultprettyprinter().writevalueasstring(wanger);

system.out.println(jsonstring);

cmower deserialize = mapper.readvalue(jsonstring,cmower.class);
system.out.println(deserialize);

objectmapper 通过 writevalue() 的系列方法可以将 java 对象序列化为 json,并将 json 存储成不同的格式。

  • string(writevalueasstring)
  • byte array(writevalueasbytes)

objectmapper 通过 readvalue() 系列方法可以从不同的数据源(string、bytes)将 json 反序列化(解析)为 java 对象。

程序输出结果为:

com.cmower.java_demo.jackson.cmower@214c265e
{
  "age" : 18,
  "name" : "沉默王二"
}
com.cmower.java_demo.jackson.cmower@612fc6eb

在调用 writevalue() 或者 readvalue() 方法之前,往往需要对 json 和 javabean 之间进行一些定制化配置。

1)在反序列化时忽略在 json 中存在但 javabean 不存在的字段

mapper.configure(deserializationfeature.fail_on_unknown_properties, false);

2)在序列化时忽略值为 null 的字段

apper.setserializationinclusion(include.non_null); 

有些时候,这些定制化的配置对 json 和 javabean 之间的转化起着重要的作用。如果需要更多配置信息,查看 deserializationfeature、serializationfeature 和 include 类的 javadoc 即可。

关于 jackson,我们就说到这吧,以后有机会的时候再和大家细说。

04、org.json

org.json 是 json 官方提供的一个开源库,不过使用起来就略显繁琐了。

使用 org.json 之前,需要先在项目中引入 org.json 的依赖。

<dependency>
    <groupid>org.json</groupid>
    <artifactid>json</artifactid>
    <version>20190722</version>
</dependency>

org.json.jsonobject 类可以通过 new 关键字将 json 字符串解析为 java 对象,然后 get 的系列方法获取对应的键值,代码示例如下所示。

string str = "{ \"name\": \"沉默王二\", \"age\": 18 }";
jsonobject obj = new jsonobject(str);
string name = obj.getstring("name");
int age = obj.getint("age");

调用 org.json.jsonobject 类的 getjsonarray() 方法可以返回一个表示数组的org.json.jsonarray 对象,再通过循环的方式可以获取数组中的元素,代码示例如下所示。

string str = "{ \"number\": [3, 4, 5, 6] }";
jsonobject obj = new jsonobject(str);
jsonarray arr = obj.getjsonarray("number");
for (int i = 0; i < arr.length(); i++) {
    system.out.println(arr.getint(i));
}

如果想获取 json 字符串,可以使用 put() 方法将键值对放入 org.json.jsonobject 对象中,再调用 tostring() 方法即可,代码示例如下所示。

jsonobject obj = new jsonobject();
obj.put("name","沉默王二");
obj.put("age",18);
system.out.println(obj.tostring()); // {"name":"沉默王二","age":18}

相比较于 gson 和 jackson 来说,org.json 就要逊色多了,不仅不够灵活,api 也不够丰富。

05、fastjson

fastjson 是阿里巴巴开源的 json 解析库,它可以解析 json 格式的字符串,也支持将 java bean 序列化为 json 字符串。

fastjson 相对于其他 json 库的特点就是快,另外 api 使用起来也非常简单,更是在 2012 年被开源中国评选为最受欢迎的国产开源软件之一。

ps:尽管 fastjson 值得信赖,但也闹过不少腥风血雨,这里就不提了。

在使用 fastjson 之前,需要先添加 fastjson 的依赖。

<dependency>
    <groupid>com.alibaba</groupid>
    <artifactid>fastjson</artifactid>
    <version>1.2.61</version>
</dependency>

那怎么使用 fastjson 呢?我们来创建一个 java bean,有三个字段:年龄 age,名字 name,列表 books。

class cmower1 {
    private integer age;
    private string name;
    private list<string> books = new arraylist<>();

    public cmower1(integer age, string name) {
        this.age = age;
        this.name = name;
    }
   // getter/setter

    public void putbook(string bookname) {
        this.books.add(bookname);
    }
}

然后我们使用 json.tojsonstring() 将 java 对象序列化为 json 字符串,代码示例如下:

cmower1 cmower = new cmower1(18,"沉默王二");
cmower.putbook("《web全栈开发进阶之路》");
string jsonstring = json.tojsonstring(cmower);
system.out.println(jsonstring);

程序输出:

{"age":18,"books":["《web全栈开发进阶之路》"],"name":"沉默王二"}

那如何解析 json 字符串呢?使用 json.parseobject() 方法,代码示例如下所示。

json.parseobject(jsonstring, cmower1.class)

06、总结

就我个人而言,我是比较推崇 gson 的,毕竟是谷歌出品的,品质值得信赖,关键是用起来也确实比较得劲。

jackson 呢,在解析大的 json 文件时速度更快,也比 fastjson 稳定。

fastjson 呢,作为我们国产开源软件中的骄傲,嗯,值得尊敬。

令我意外的是,org.json 在 * 上一个 160 万浏览量的提问中,牢牢地占据头名答案。更令我想不到的是,老板竟然也选择了 org.json,说它比较原生,json 官方的亲儿子。

我。。。。。。

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?

07、鸣谢

好了,各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,升职加薪就是你了

(0)
打赏 除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器? 微信扫一扫

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?
验证码: 除了闹过腥风血雨的fastjson,你还知道哪些Java解析JSON的利器?