2.java程序员必知必会类库之json解析库

news/2024/7/24 4:02:09 标签: java, json, fastjson, Gson

前言

百度百科解释

JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在当今世界的web服务的数据交互中,JSON已经取代了XML,成为从客户端到服务器传送信息的首选协议。有一个好消息和一个坏消息。坏消息是JDK没有提供JSON库。好消息是有许多优秀的第三方库可以用来解析和创建JSON消息,如 fastjsonGson

json_5">fastjson

1.介绍

Git地址: https://github.com/alibaba/fastjson
Wiki:https://github.com/alibaba/fastjson/wiki
FAQ:https://github.com/alibaba/fastjson/wiki/常见问题

2. 使用

2.1. pom依赖引入

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

2.2 api使用

2.2.1 序列化对象转字符串
java">public class User {

    private String username;

    private Date birthday;

    private int sex;

//省略getset tostring方法
}
User user = new User();
user.setBirthday(new Date());
user.setSex(1);
user.setUsername("liming");

User user2=new User();
user2.setUsername("wangpeng");
user2.setSex(0);
user2.setBirthday(new Date());

List<User> userList=new ArrayList<User>();
userList.add(user);
userList.add(user2);
System.out.println(JSON.toJSONString(userList));
//[{"birthday":1681351631631,"sex":1,"username":"liming"},{"birthday":1681351631631,"sex":0,"username":"wangpeng"}]

String str = JSONObject.toJSONString(user);
System.out.println(str);
//{"birthday":1681350602343,"sex":1,"username":"liming"}

这里jsonobject 和 JSONArray 实际继承的都是抽象父类JSON,两个类的很多方法实际都用的是JSON的方法,比如toJSONString

2.2.2 反序列化字符串转对象
java">String str="{\"birthday\":1681350739299,\"sex\":1,\"username\":\"liming\"}";
User user = JSONObject.parseObject(str, User.class);
System.out.println(user.toString());
//User{username='liming', birthday=Thu Apr 13 09:52:19 CST 2023, sex=1}

String str2="[{\"birthday\":1681351631631,\"sex\":1,\"username\":\"liming\"},{\"birthday\":1681351631631,\"sex\":0,\"username\":\"wangpeng\"}]";
List<User> users = JSONArray.parseArray(str2, User.class);
System.out.println(users);
//[User{username='liming', birthday=Thu Apr 13 10:07:11 CST 2023, sex=1}, User{username='wangpeng', birthday=Thu Apr 13 10:07:11 CST 2023, sex=0}]

3.注意事项

3.1 版本问题

之前fastjson出现漏洞,为此,出于安全考虑,需要升级公司fastjson版本到1.2.83 以上,关于漏洞更多信息,可网上找相关内容深入了解

3.2 循环引用的问题

当进行toJSONString的时候,默认如果重用对象的话,会使用引用的方式进行引用对象。,详见下面代码示例

java">A a = new A();
B b = new B();
a.setB(b);
ArrayList<Object> objects = new ArrayList<Object>();
objects.add(a);
//这里和a重用b对象
objects.add(b);
String string = JSON.toJSONString(objects);
//可以看到序列化出来的数据带引用
System.out.println(string); //[{"b":{}},{"$ref":"$[0].b"}]
JSONArray array = JSON.parseArray(string);
//反序列化也可以看到实际引用对象地址是一样的
boolean isTheSameObject = array.getJSONObject(0).getJSONObject("b") == array.getJSONObject(1);
System.out.println(isTheSameObject);//true
//去除循环依赖检测
String deleteRefrenceStr = JSON.toJSONString(objects, SerializerFeature.DisableCircularReferenceDetect);
System.out.println(deleteRefrenceStr); //[{"b":{}},{}]
// 去除循环依赖后反序列化,可以看到生成的对象与原来的没有关系
JSONArray array2=JSON.parseArray(deleteRefrenceStr);
System.out.println(array2.getJSONObject(0).getJSONObject("b") == array2.getJSONObject(1));
//false

3.3 常见注解使用

3.3.1 JSONField注解

该注解主要用于在序列化和反序列化的时候,对我们要处理的对象做一些自己想要的定制化配置,而不是用通用的处理,注解属性如下:

java">package com.alibaba.fastjson.annotation;
public @interface JSONField {
    // 配置序列化和反序列化的顺序,1.1.42版本之后才支持
    int ordinal() default 0;

     // 指定字段的名称
    String name() default "";

    // 指定字段的格式,对日期格式有用
    String format() default "";

    // 是否序列化
    boolean serialize() default true;

    // 是否反序列化
    boolean deserialize() default true;
}

下面通过几个简单的例子展示如何使用该注解
注意:1、若属性是私有的,必须有set*方法。否则无法反序列化。

java"> public class A {
      @JSONField(name="ID")
      private int id;
 
      @JSONField(name="ID")
      public int getId() {return id;}
      @JSONField(name="ID")
      public void setId(int value) {this.id = id;}
      
     // 配置date序列化和反序列使用yyyyMMdd日期格式
      @JSONField(format="yyyyMMdd")
      public Date date;
      // 使用serialize/deserialize指定字段不序列化
 	  @JSONField(serialize=false)
      public Date birthday;
	  //缺省fastjson序列化一个java bean,是根据fieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本
   	  @JSONField(ordinal = 3)
      private int f0;
      @JSONField(ordinal = 2)
      private int f1;
      @JSONField(ordinal = 1)
      private int f2;
 }
3.3.1.1 使用serializeUsing制定属性的序列化类

在fastjson 1.2.16版本之后,JSONField支持新的定制化配置serializeUsing,可以单独对某一个类的某个属性定制序列化,

java">public static class Model {
    @JSONField(serializeUsing = ModelValueSerializer.class)
    public int value;
}

public static class ModelValueSerializer implements ObjectSerializer {
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                      int features) throws IOException {
        Integer value = (Integer) object;
        String text = value + "元";
        serializer.write(text);
    }
}

Model model = new Model();
model.value = 100;
String json = JSON.toJSONString(model);
Assert.assertEquals("{\"value\":\"100元\"}", json);
3.3.2 JSONType注解

在1.2.14版本之后,fastjson支持通过JSONType配置定制序列化的ObjectSerializer。使用如下

java">@JSONType(serializer=ModelSerializer.class)
public static class Model {
    public int id;
}

public static class ModelSerializer implements ObjectSerializer {

    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                      int features) throws IOException {
        Model model = (Model) object;
        SerializeWriter out = serializer.getWriter();
        out.writeFieldValue('{', "ID", model.id);
        out.write('}');
    }
}
Model model = new Model();
model.id = 1001;
String text = JSON.toJSONString(model);
Assert.assertEquals("{\"ID\":1001}", text);

3.4 序列化特性使用

上面有提到序列化去除循环依赖的使用特性,fastjson 也提供了很多其他序列化方式,这些序列化方式可以一起组合使用。下面代码我是从fastjson 源码里拷贝过来的。
通过英文名基本就能猜到使用相应特性的结果,这里就不一一赘述。

java">public enum SerializerFeature {
QuoteFieldNames,
UseSingleQuotes,
WriteMapNullValue,
WriteEnumUsingToString,
WriteEnumUsingName,
UseISO8601DateFormat,
WriteNullListAsEmpty,
WriteNullStringAsEmpty,
WriteNullNumberAsZero,
WriteNullBooleanAsFalse,
SkipTransientField,
SortField,
/** @deprecated */
@Deprecated
WriteTabAsSpecial,
PrettyFormat,
WriteClassName,
DisableCircularReferenceDetect,
WriteSlashAsSpecial,
BrowserCompatible,
WriteDateUseDateFormat,
NotWriteRootClassName,
/** @deprecated */
DisableCheckSpecialChar,
BeanToArray,
WriteNonStringKeyAsString,
NotWriteDefaultValue,
BrowserSecure,
IgnoreNonFieldGetter,
WriteNonStringValueAsString,
IgnoreErrorGetter,
WriteBigDecimalAsPlain,
MapSortField;
}

3.5 自定义序列化与反序列化

3.5.1 自定义序列化

参考官网,不再赘述

3.5.2 自定义反序列化

参考官网,不再赘述

4.与spring结合

参考官网介绍

Gson_239">Gson

1.介绍

GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。GSON笔者使用不多,这里只做简单介绍

2. 使用

2.1 pom坐标

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.8.5</version>
</dependency>

2.2 api使用

2.2.1 对象序列化与反序列化demo
java">
User user = new User();
user.setBirthday(new Date());
user.setSex(1);
user.setUsername("liming");
//序列化  基本类型有默认值,包装类不解析
String str = new Gson().toJson(user);
System.out.println(str);
//{"username":"liming","birthday":"Apr 13, 2023 3:37:26 PM","sex":1}
User user2=new User();
user2.setUsername("wangpeng");
user2.setBirthday(new Date());
System.out.println(new Gson().toJson(user2));
//{"username":"wangpeng","birthday":"Apr 13, 2023 3:39:13 PM","sex":0}

//反序列化
User userDeseri = new Gson().fromJson(str, User.class);
System.out.println(userDeseri);
//User{username='liming', birthday=Thu Apr 13 15:40:48 CST 2023, sex=1}
2.2.2 集合序列化与反序列化demo
java">User user = new User();
user.setBirthday(new Date());
user.setSex(1);
user.setUsername("liming");

User user2=new User();
user2.setUsername("wangpeng");
user2.setBirthday(new Date());

List<User> userList=new ArrayList<User>();
userList.add(user);
userList.add(user2);
//集合序列化
String toJsonStr = new Gson().toJson(userList);
System.out.println(toJsonStr);
//[{"username":"liming","birthday":"Apr 13, 2023 3:48:50 PM","sex":1},{"username":"wangpeng","birthday":"Apr 13, 2023 3:48:50 PM","sex":0}]
//集合反序列化
Type type = new TypeToken<ArrayList<User>>(){}.getType();
List<User> users = new Gson().fromJson(toJsonStr, type);
System.out.println(users);
//[User{username='liming', birthday=Thu Apr 13 15:48:50 CST 2023, sex=1}, User{username='wangpeng', birthday=Thu Apr 13 15:48:50 CST 2023, sex=0}]

3.注意事项

3.1 指定序列化和反序列化字段名称

通过该注解,可以在序列化和反序列化的时候调整属性名称

java">public class User {
    @SerializedName("testuser")
    private String username;
    private Date birthday;
    private int sex;
}
User user = new User();
user.setBirthday(new Date());
user.setSex(1);
user.setUsername("liming");
String str = new Gson().toJson(user);
//{"testuser":"liming","birthday":"Apr 13, 2023 4:03:08 PM","sex":1}

3.2 忽略解析某个值

使用transient关键字修饰的属性,不参与序列化

java">public class User {

    private String username;
    private Date birthday;
    private transient int sex;
}
User user = new User();
user.setBirthday(new Date());
user.setSex(1);
user.setUsername("liming");
String str = new Gson().toJson(user);
//{"username":"liming","birthday":"Apr 13, 2023 3:56:22 PM"}

参考文献:
阿里巴巴fastjson github


http://www.niftyadmin.cn/n/229634.html

相关文章

查询练习:表示所有的 ALL

查询课程 3-105 且成绩高于 3-245 的 score 表。 -- 只需对上一道题稍作修改。 -- ALL: 符合SQL语句中的所有条件。 -- 也就是说&#xff0c;在 3-105 每一行成绩中&#xff0c;都要大于从 3-245 筛选出来全部行才算符合条件。 SELECT * FROM score WHERE c_no 3-105 AND deg…

LeetCode笔记:Biweekly Contest 102

LeetCode笔记&#xff1a;Biweekly Contest 102 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接&#xff1a;https://leetcode.com/contest/biweekly-contest-102 1. 题目…

【C语言 -结构体 结构体声明、定义、初始化、结构体成员访问、结构体传参】

C语言 - 结构体声明、定义、初始化、结构体成员访问、结构体传参一 结构体类型的声明&#xff1a;声明格式&#xff1a;二 结构体的定义并初始化2.1用结构体创建&#xff08;定义&#xff09;结构体变量&#xff08;对象&#xff09;的两种方式&#xff1a;&#xff08;1&#…

elasticsearch-7.17.9

1、ElasticSearch 1.1、概念 1.1.1、分片(shard) 1、分片 在ES中所有数据的文件块&#xff0c;也是数据的最小单元块&#xff0c;整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度。 实列场景&#xff1a; 假设 IndexA 有2个分片&#xff0c;向 I…

Linux项目日志管理log4cpp的安装与使用【结合sample】

文章目录前言log4cpp安装log4cpp的使用设置类别输出的&#xff08;category&#xff09;和日志优先级&#xff08;priority&#xff09;定义一个宏用于输出日志配置文件使用log4cpp的栗子结语前言 我们都清楚对于一个项目来说它的日志信息是非常重要的&#xff0c;那么我们应该…

Scala操作列表List、数组Array和集合Set

1、Scala操作List 1.1 初始化List scala> val list0 List(9, 2, 8, 3, 4, 5, 6, 7) list0: List[Int] List(9, 2, 8, 3, 4, 5, 6, 7)1.2 List过滤筛选 // 筛选偶数 scala> list0.filter(_ % 2 0) res0: List[Int] List(2, 8, 4, 6)list0.filter(_ % 2 0) 等价于l…

【MySQL | 基础篇】02、MySQL 函数详解

目录 一、字符串函数 1.1 concat : 字符串拼接 1.2 lower : 全部转小写 1.3 upper : 全部转大写 1.4 lpad : 左填充 1.5 rpad : 右填充 1.6 trim : 去除空格 1.7 substring : 截取子字符串 1.8 案例 二、数值函数 2.1 ceil&#xff1a;向上取整 2.2 floor&#xff…

借助高性能计算的发展十大网络趋势

当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能/深度学习的应用程序&#xff0c;企业可以满足对更快计算周期、更高数据传输率和出色连接性日益增长的需求。 当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能…