当前位置:   article > 正文

Fastjson详解_fastjson jsonpath.eval

fastjson jsonpath.eval

Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。

主要特点:

  • 快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)
  • 强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)
  • 零依赖(没有依赖其它任何类库除了JDK)

例如:

  1. import com.alibaba.fastjson.JSON;
  2. Group group = new Group();
  3. group.setId(0L);
  4. group.setName("admin");
  5. User guestUser = new User();
  6. guestUser.setId(2L);
  7. guestUser.setName("guest");
  8. User rootUser = new User();
  9. rootUser.setId(3L);
  10. rootUser.setName("root");
  11. group.getUsers().add(guestUser);
  12. group.getUsers().add(rootUser);
  13. String jsonString = JSON.toJSONString(group);
  14. System.out.println(jsonString);

JSON这个类是fastjson API的入口,主要的功能都通过这个类提供。

序列化API

  1. package com.alibaba.fastjson;
  2. public abstract class JSON {
  3. // 将Java对象序列化为JSON字符串,支持各种各种Java基本类型和JavaBean
  4. public static String toJSONString(Object object, SerializerFeature... features);
  5. // 将Java对象序列化为JSON字符串,返回JSON字符串的utf-8 bytes
  6. public static byte[] toJSONBytes(Object object, SerializerFeature... features);
  7. // 将Java对象序列化为JSON字符串,写入到Writer中
  8. public static void writeJSONString(Writer writer,
  9. Object object,
  10. SerializerFeature... features);
  11. // 将Java对象序列化为JSON字符串,按UTF-8编码写入到OutputStream中
  12. public static final int writeJSONString(OutputStream os, //
  13. Object object, //
  14. SerializerFeature... features);
  15. }

JSON字符串反序列化API

  1. package com.alibaba.fastjson;
  2. public abstract class JSON {
  3. // 将JSON字符串反序列化为JavaBean
  4. public static <T> T parseObject(String jsonStr,
  5. Class<T> clazz,
  6. Feature... features);
  7. // 将JSON字符串反序列化为JavaBean
  8. public static <T> T parseObject(byte[] jsonBytes, // UTF-8格式的JSON字符串
  9. Class<T> clazz,
  10. Feature... features);
  11. // 将JSON字符串反序列化为泛型类型的JavaBean
  12. public static <T> T parseObject(String text,
  13. TypeReference<T> type,
  14. Feature... features);
  15. // 将JSON字符串反序列为JSONObject
  16. public static JSONObject parseObject(String text);
  17. }

接下来看:

parseTree

  1. import com.alibaba.fastjson.*;
  2. JSONObject jsonObj = JSON.parseObject(jsonStr);

parse pojo

  1. import com.alibaba.fastjson.JSON;
  2. Model model = JSON.parseObject(jsonStr, Model.class);

parse pojo generic

  1. import com.alibaba.fastjson.JSON;
  2. Type type = new TypeReference<List<Model>>() {}.getType();
  3. List<Model> list = JSON.parseObject(jsonStr, type);

convert pojo to json string

  1. import com.alibaba.fastjson.JSON;
  2. Model model = ...;
  3. String jsonStr = JSON.toJSONString(model);

convert pojo to json bytes

  1. import com.alibaba.fastjson.JSON;
  2. Model model = ...;
  3. byte[] jsonBytes = JSON.toJSONBytes(model);

JSONField 介绍

注意:1、若属性是私有的,必须有set*方法。否则无法反序列化。

  1. package com.alibaba.fastjson.annotation;
  2. public @interface JSONField {
  3. // 配置序列化和反序列化的顺序,1.1.42版本之后才支持
  4. int ordinal() default 0;
  5. // 指定字段的名称
  6. String name() default "";
  7. // 指定字段的格式,对日期格式有用
  8. String format() default "";
  9. // 是否序列化
  10. boolean serialize() default true;
  11. // 是否反序列化
  12. boolean deserialize() default true;
  13. }

JSONField配置方式

FieldInfo可以配置在getter/setter方法或者字段上。例如:

配置在getter/setter上

  1. public class A {
  2. private int id;
  3. @JSONField(name="ID")
  4. public int getId() {return id;}
  5. @JSONField(name="ID")
  6. public void setId(int value) {this.id = id;}
  7. }

配置在field上

  1. public class A {
  2. @JSONField(name="ID")
  3. private int id;
  4. public int getId() {return id;}
  5. public void setId(int value) {this.id = id;}
  6. }

使用format配置日期格式化

  1. public class A {
  2. // 配置date序列化和反序列使用yyyyMMdd日期格式
  3. @JSONField(format="yyyyMMdd")
  4. public Date date;
  5. }

使用serialize/deserialize指定字段不序列化

  1. public class A {
  2. @JSONField(serialize=false)
  3. public Date date;
  4. }
  5. public class A {
  6. @JSONField(deserialize=false)
  7. public Date date;
  8. }

使用ordinal指定字段的顺序

  1. public static class VO {
  2. @JSONField(ordinal = 3)
  3. private int f0;
  4. @JSONField(ordinal = 2)
  5. private int f1;
  6. @JSONField(ordinal = 1)
  7. private int f2;
  8. }

使用serializeUsing制定属性的序列化类

  1. public static class Model {
  2. @JSONField(serializeUsing = ModelValueSerializer.class)
  3. public int value;
  4. }
  5. public static class ModelValueSerializer implements ObjectSerializer {
  6. @Override
  7. public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
  8. int features) throws IOException {
  9. Integer value = (Integer) object;
  10. String text = value + "元";
  11. serializer.write(text);
  12. }
  13. }

测试代码

  1. Model model = new Model();
  2. model.value = 100;
  3. String json = JSON.toJSONString(model);
  4. Assert.assertEquals("{\"value\":\"100元\"}", json);

看一个DEMO

  1. public static class Model {
  2. public int id;
  3. @JSONField(alternateNames = {"user", "person"})
  4. public String name;
  5. }
  6. String jsonVal0 = "{\"id\":5001,\"name\":\"Jobs\"}";
  7. String jsonVal1 = "{\"id\":5382,\"user\":\"Mary\"}";
  8. String jsonVal2 = "{\"id\":2341,\"person\":\"Bob\"}";
  9. Model obj0 = JSON.parseObject(jsonVal0, Model.class);
  10. assertEquals(5001, obj0.id);
  11. assertEquals("Jobs", obj0.name);
  12. Model obj1 = JSON.parseObject(jsonVal1, Model.class);
  13. assertEquals(5382, obj1.id);
  14. assertEquals("Mary", obj1.name);
  15. Model obj2 = JSON.parseObject(jsonVal2, Model.class);
  16. assertEquals(2341, obj2.id);
  17. assertEquals("Bob", obj2.name);

JSONField jsonDirect

在fastjson-1.2.12版本中,JSONField支持一个新的配置项jsonDirect,它的用途是:当你有一个字段是字符串类型,里面是json格式数据,你希望直接输入,而不是经过转义之后再输出。

Model

  1. import com.alibaba.fastjson.annotation.JSONField;
  2. public static class Model {
  3. public int id;
  4. @JSONField(jsonDirect=true)
  5. public String value;
  6. }

Usage

  1. Model model = new Model();
  2. model.id = 1001;
  3. model.value = "{}";
  4. String json = JSON.toJSONString(model);
  5. Assert.assertEquals("{\"id\":1001,\"value\":{}}", json);

JSONPath介绍

fastjson 1.2.0之后的版本支持JSONPath。这是一个很强大的功能,可以在java框架中当作对象查询语言(OQL)来使用。

API:

  1. package com.alibaba.fastjson;
  2. public class JSONPath {
  3. // 求值,静态方法
  4. public static Object eval(Object rootObject, String path);
  5. // 计算Size,Map非空元素个数,对象非空元素个数,Collection的Size,数组的长度。其他无法求值返回-1
  6. public static int size(Object rootObject, String path);
  7. // 是否包含,path中是否存在对象
  8. public static boolean contains(Object rootObject, String path) { }
  9. // 是否包含,path中是否存在指定值,如果是集合或者数组,在集合中查找value是否存在
  10. public static boolean containsValue(Object rootObject, String path, Object value) { }
  11. // 修改制定路径的值,如果修改成功,返回true,否则返回false
  12. public static boolean set(Object rootObject, String path, Object value) {}
  13. // 在数组或者集合中添加元素
  14. public static boolean array_add(Object rootObject, String path, Object... values);
  15. }

建议缓存JSONPath对象,这样能够提高求值的性能

 支持语法

JSONPATH描述
$根对象,例如$.name
[num]数组访问,其中num是数字,可以是负数。例如$[0].leader.departments[-1].name
[num0,num1,num2...]数组多个元素访问,其中num是数字,可以是负数,返回数组中的多个元素。例如$[0,3,-2,5]
[start:end]数组范围访问,其中start和end是开始小表和结束下标,可以是负数,返回数组中的多个元素。例如$[0:5]
[start:end :step]数组范围访问,其中start和end是开始小表和结束下标,可以是负数;step是步长,返回数组中的多个元素。例如$[0:5:2]
[?(key)]对象属性非空过滤,例如$.departs[?(name)]
[key > 123]数值类型对象属性比较过滤,例如$.departs[id >= 123],比较操作符支持=,!=,>,>=,<,<=
[key = '123']字符串类型对象属性比较过滤,例如$.departs[name = '123'],比较操作符支持=,!=,>,>=,<,<=
[key like 'aa%']字符串类型like过滤,
例如$.departs[name like 'sz*'],通配符只支持% 
支持not like
[key rlike 'regexpr']字符串类型正则匹配过滤,
例如departs[name like 'aa(.)*'],
正则语法为jdk的正则语法,支持not rlike
[key in ('v0', 'v1')]IN过滤, 支持字符串和数值类型 
例如: 
$.departs[name in ('wenshao','Yako')] 
$.departs[id not in (101,102)]
[key between 234 and 456]BETWEEN过滤, 支持数值类型,支持not between 
例如: 
$.departs[id between 101 and 201]
$.departs[id not between 101 and 201]
length() 或者 size()数组长度。例如$.values.size() 
支持类型java.util.Map和java.util.Collection和数组
.属性访问,例如$.name
..deepScan属性访问,例如$..name
*对象的所有属性,例如$.leader.*
['key']属性访问。例如$['name']
['key0','key1']多个属性访问。例如$['id','name']

以下两种写法的语义是相同的:

  1. $.store.book[0].title
  2. $['store']['book'][0]['title']

语法示例

JSONPath语义
$根对象
$[-1]最后元素
$[:-2]第1个至倒数第2个
$[1:]第2个之后所有元素
$[1,2,3]

集合中1,2,3个元素

API 示例

  1. public void test_entity() throws Exception {
  2. Entity entity = new Entity(123, new Object());
  3. Assert.assertSame(entity.getValue(), JSONPath.eval(entity, "$.value"));
  4. Assert.assertTrue(JSONPath.contains(entity, "$.value"));
  5. Assert.assertTrue(JSONPath.containsValue(entity, "$.id", 123));
  6. Assert.assertTrue(JSONPath.containsValue(entity, "$.value", entity.getValue()));
  7. Assert.assertEquals(2, JSONPath.size(entity, "$"));
  8. Assert.assertEquals(0, JSONPath.size(new Object[], "$"));
  9. }
  10. public static class Entity {
  11. private Integer id;
  12. private String name;
  13. private Object value;
  14. public Entity() {}
  15. public Entity(Integer id, Object value) { this.id = id; this.value = value; }
  16. public Entity(Integer id, String name) { this.id = id; this.name = name; }
  17. public Entity(String name) { this.name = name; }
  18. public Integer getId() { return id; }
  19. public Object getValue() { return value; }
  20. public String getName() { return name; }
  21. public void setId(Integer id) { this.id = id; }
  22. public void setName(String name) { this.name = name; }
  23. public void setValue(Object value) { this.value = value; }
  24. }

读取集合多个元素的某个属性

  1. List<Entity> entities = new ArrayList<Entity>();
  2. entities.add(new Entity("wenshao"));
  3. entities.add(new Entity("ljw2083"));
  4. List<String> names = (List<String>)JSONPath.eval(entities, "$.name"); // 返回enties的所有名称
  5. Assert.assertSame(entities.get(0).getName(), names.get(0));
  6. Assert.assertSame(entities.get(1).getName(), names.get(1));

返回集合中多个元素

  1. List<Entity> entities = new ArrayList<Entity>();
  2. entities.add(new Entity("wenshao"));
  3. entities.add(new Entity("ljw2083"));
  4. entities.add(new Entity("Yako"));
  5. List<Entity> result = (List<Entity>)JSONPath.eval(entities, "[1,2]"); // 返回下标为1和2的元素
  6. Assert.assertEquals(2, result.size());
  7. Assert.assertSame(entities.get(1), result.get(0));
  8. Assert.assertSame(entities.get(2), result.get(1));

按范围返回集合的子集

  1. List<Entity> entities = new ArrayList<Entity>();
  2. entities.add(new Entity("wenshao"));
  3. entities.add(new Entity("ljw2083"));
  4. entities.add(new Entity("Yako"));
  5. List<Entity> result = (List<Entity>)JSONPath.eval(entities, "[0:2]"); // 返回下标从0到2的元素
  6. Assert.assertEquals(3, result.size());
  7. Assert.assertSame(entities.get(0), result.get(0));
  8. Assert.assertSame(entities.get(1), result.get(1));
  9. Assert.assertSame(entities.get(2), result.get(1));

通过条件过滤,返回集合的子集

  1. List<Entity> entities = new ArrayList<Entity>();
  2. entities.add(new Entity(1001, "ljw2083"));
  3. entities.add(new Entity(1002, "wenshao"));
  4. entities.add(new Entity(1003, "yakolee"));
  5. entities.add(new Entity(1004, null));
  6. List<Object> result = (List<Object>) JSONPath.eval(entities, "[id in (1001)]");
  7. Assert.assertEquals(1, result.size());
  8. Assert.assertSame(entities.get(0), result.get(0));

根据属性值过滤条件判断是否返回对象,修改对象,数组属性添加元素

  1. Entity entity = new Entity(1001, "ljw2083");
  2. Assert.assertSame(entity , JSONPath.eval(entity, "[id = 1001]"));
  3. Assert.assertNull(JSONPath.eval(entity, "[id = 1002]"));
  4. JSONPath.set(entity, "id", 123456); //将id字段修改为123456
  5. Assert.assertEquals(123456, entity.getId().intValue());
  6. JSONPath.set(entity, "value", new int[0]); //将value字段赋值为长度为0的数组
  7. JSONPath.arrayAdd(entity, "value", 1, 2, 3); //将value字段的数组添加元素1,2,3

接下来看:

  1. Map root = Collections.singletonMap("company", //
  2. Collections.singletonMap("departs", //
  3. Arrays.asList( //
  4. Collections.singletonMap("id",
  5. 1001), //
  6. Collections.singletonMap("id",
  7. 1002), //
  8. Collections.singletonMap("id", 1003) //
  9. ) //
  10. ));
  11. List<Object> ids = (List<Object>) JSONPath.eval(root, "$..id");
  12. assertEquals(3, ids.size());
  13. assertEquals(1001, ids.get(0));
  14. assertEquals(1002, ids.get(1));
  15. assertEquals(1003, ids.get(2));

以上就暂时介绍这么多了。下次有时间在整理吧。

有问题可以在下面评论,技术问题可以私聊我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/911943
推荐阅读
相关标签
  

闽ICP备14008679号