赞
踩
JSON是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
json的一般格式:由花括号包裹多个键值对,键值对的值可以是字符串,也可以是Json格式或者数组 []
{
key1 : "value1",
key2 : "value2",
key3 : {
key4 : "value4",
key5 : []
}
}
fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
fastjson的API十分简洁。
String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化
支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。
(以上粘自fastjson的wiki)
如同上面的介绍,fastjson的api十分简单,对象转换成json串或从json串转换为对象每个操作都只要一行就能完成,下面就对fastjson的部分功能进行测试。
首先需要一个类,用于转换成json串,类中fastjson的注解会一一解释。
import com.alibaba.fastjson.annotation.JSONField; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @NoArgsConstructor // 无参构造函数 @AllArgsConstructor // 全参构造函数 @Data // get/set/tostring public class User { @JSONField(name = "id", ordinal = 1) private Integer id; @JSONField(name = "姓名", ordinal = 2) private String name; @JSONField(name = "年龄", ordinal = 3) private Integer age; @JSONField(name = "性别", ordinal = 4) private String gender; @JSONField(name = "地址", ordinal = 5) private String address; @JSONField(name = "生日", format = "yyyy-MM-dd", ordinal = 6, alternateNames = {"出生日期","生日"}) private Date birth; @JSONField(name = "爱好", ordinal = 7) private String[] hobbits; }
测试转换成json和从json转回
@Test
public void testJsonFiledSerializable() {
System.out.println(JSON.toJSONString(new User(1, "张三", 25, "男", "北京市",new Date(),new String[]{})));
System.out.println(JSON.parseObject("{\"id\":1,\"姓名\":\"张三\",\"年龄\":25,\"性别\":\"男\",\"地址\":\"北京市\",\"生日\":\"2020-12-12\",\"爱好\":[]}", User.class));
System.out.println(JSON.parseObject("{\"id\":1,\"姓名\":\"张三\",\"年龄\":25,\"性别\":\"男\",\"地址\":\"北京市\",\"出生日期\":\"2020-12-12\",\"爱好\":[]}", User.class));
}
输出结果为
{"id":1,"姓名":"张三","年龄":25,"性别":"男","地址":"北京市","生日":"2020-12-12","爱好":[]}
User(id=1, name=张三, age=25, gender=男, address=北京市, birth=Sat Dec 12 00:00:00 CST 2020, hobbits=[])
User(id=1, name=张三, age=25, gender=男, address=北京市, birth=Sat Dec 12 00:00:00 CST 2020, hobbits=[])
接下来尝试在类中定义一个类作为成员变量,查看是否能够转换成功
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TUser {
@JSONField(name = "介绍", ordinal = 0)
private String name;
@JSONField(name = "用户", ordinal = 1)
private User user;
}
测试:
@Test
public void testMatryoshka() {
User user = new User(1, "张三", 25, "男", "北京市", new Date(), new String[]{"唱歌"});
TUser user1 = new TUser("测试套娃", user);
System.out.println(JSON.toJSONString(user1));
System.out.println(JSON.parseObject("{\"介绍\":\"测试套娃\",\"用户\":{\"id\":1,\"姓名\":\"张三\",\"年龄\":25,\"性别\":\"男\",\"地址\":\"北京市\", \"生日\":\"2020-12-12\",\"爱好\":[\"唱歌\"]}}",TUser.class));
}
这个测试类的结果为:
{"介绍":"测试套娃","用户":{"id":1,"姓名":"张三","年龄":25,"性别":"男","地址":"北京市","生日":"2020-12-12","爱好":["唱歌"]}}
TUser(name=测试套娃, user=User(id=1, name=张三, age=25, gender=男, address=北京市, birth=Sat Dec 12 00:00:00 CST 2020, hobbits=[唱歌]))
可以看到,json和对象之间的转换十分平滑。
下面来讲解一下 @JSONField 注解
@JSONField注解标记在成员变量上或者get/set方法上,被标记的成员变量必须有对应的get/set方法,在这里我直接使用lombok的注解帮忙生成了,减少代码量。
可以看到,在输出的json串中,并没有使用定义的字段名,是因为在注解中加入了name参数,在对象转成json串时会将字段名替换成name的值。
同时,输出的json串的顺序是由 ordinal 决定的,默认值为0,在它的值相等时会随机顺序输出。
可以看到输出的日期也是格式化后的,这个是由format参数控制的,可以设置各种格式,如 “yyyy-MM-dd” \ “yyyy年MM月dd日”
在json串转user类时,可以看到 ‘生日’ 和 ‘出生日期’ 都可以转换成user对象,这是配置了别名,使用 alternateNames
fastjson中还有JSONPath 可以很方便的操作
package com.alibaba.fastjson; public class JSONPath { // 求值,静态方法 public static Object eval(Object rootObject, String path); // 计算Size,Map非空元素个数,对象非空元素个数,Collection的Size,数组的长度。其他无法求值返回-1 public static int size(Object rootObject, String path); // 是否包含,path中是否存在对象 public static boolean contains(Object rootObject, String path) { } // 是否包含,path中是否存在指定值,如果是集合或者数组,在集合中查找value是否存在 public static boolean containsValue(Object rootObject, String path, Object value) { } // 修改制定路径的值,如果修改成功,返回true,否则返回false public static boolean set(Object rootObject, String path, Object value) {} // 在数组或者集合中添加元素 public static boolean array_add(Object rootObject, String path, Object... values); }
当被序列化的类修改了字段的名称后,JSONPath中的方法只能根据修改后的字段名查找
@Test public void testJsonPath() { List<User> users = new ArrayList<>(); users.add(new User(1, "张三", 25, "男", "北京市", new Date(),new String[]{})); users.add(new User(2, "李四", 18, "男", "上海市", new Date(),new String[]{})); List<String> names = (List<String>) JSONPath.eval(users, "$.年龄"); System.out.println(JSONPath.size(users, "$.id")); System.out.println(JSONPath.contains(users, "$.id")); System.out.println(JSONPath.contains(users, "$.name")); System.out.println(JSONPath.containsValue(users, "$.姓名", "张三")); System.out.println(JSONPath.set(users, "$.性别", "女")); users.forEach(System.out::println); JSONPath.arrayAdd(users.get(0), "$.爱好", "唱","跳","rap"); System.out.println(users.get(0)); System.out.println(JSONPath.eval(users.get(0), "$.爱好[0]").toString()); System.out.println(JSONPath.eval(users.get(0), "$.爱好[0,1]").toString()); System.out.println(JSONPath.eval(users.get(0), "$.爱好[0:2]").toString()); System.out.println(JSONPath.eval(users, "[id in (1,3)]").toString()); System.out.println(JSONPath.eval(users, "[id = 2]").toString()); System.out.println(JSONPath.eval(users, "$..id").toString()); System.out.println(JSONPath.eval(users, "$.爱好.length()").toString()); }
该测试类输出:
2
true
false
true
true
User(id=1, name=张三, age=25, gender=女, address=北京市, birth=Sat Dec 12 21:59:52 CST 2020, hobbits=[])
User(id=2, name=李四, age=18, gender=女, address=上海市, birth=Sat Dec 12 21:59:52 CST 2020, hobbits=[])
User(id=1, name=张三, age=25, gender=女, address=北京市, birth=Sat Dec 12 21:59:52 CST 2020, hobbits=[唱, 跳, rap])
唱
["唱","跳"]
[唱, 跳, rap]
[{"id":1,"姓名":"张三","年龄":25,"性别":"女","地址":"北京市","生日":"2020-12-12","爱好":["唱","跳","rap"]}]
[{"id":2,"姓名":"李四","年龄":18,"性别":"女","地址":"上海市","生日":"2020-12-12","爱好":[]}]
[1, 2]
2
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。