您当前的位置: 首页 >  json

white camel

暂无认证

  • 0浏览

    0关注

    442博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

重学FastJson : JSON回顾、FastJson介绍、序列化API、反序列化API、SerializerFeature枚举、@JSONField详解、@JSONType使用

white camel 发布时间:2022-08-16 09:52:35 ,浏览量:0

文章目录
  • JSON回顾
  • FastJson介绍
  • 依赖引入
  • JSON抽象类、JSONObject类、JSONArray类
    • JSON类常用方法
    • JSONObject类常用方法
    • JSONArray类常用方法
  • FastJson的使用
    • FastJson序列化API
    • FashJson反序列化API
    • Java对象 转 JSON串、JSON对象
    • JSON串 转 Java对象、JSON对象
    • JSON对象 转 Java对象、JSON串
    • JSON字符串 转 List
    • JSON字符串 转 Map
  • SerializerFeature枚举
  • @JSONField注解
    • 1. @JSONField配置方式, 使用name属性
    • 2. 使用format配置日期格式化
    • 3. 使用serialize/deserialize指定字段是否序列化
    • 4. 使用ordinal指定字段的顺序 (序列化)
    • 5. 使用serializeUsing制定属性的序列化类
    • 6. JSONField alternateNames
    • 7. JSONField jsonDirect
  • @ JSONType注解

JSON回顾

JSON介绍, 什么是序列化, 反序列化

FastJson介绍
  • FastJson使用指南 Jackson的使用

FastJson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean

Fastjson 的优点

  • 速度快 fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
  • 使用广泛 fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
  • 测试完备 fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
  • 使用简单 fastjson的 API 十分简洁。
  • 功能完备 支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。
依赖引入

    com.alibaba
    fastjson
    1.2.75

JSON抽象类、JSONObject类、JSONArray类

JSON类是JSONObject和JSONArray的父类

JSON类常用方法

public abstract class JSON implements JSONStreamAware, JSONAware

  • parseObject方法 : 解析为对象(反序列化) 在这里插入图片描述
  • parseArray方法 : 解析为集合 在这里插入图片描述
  • toJSONString方法 : 转为JSON格式的字符串(序列化) 在这里插入图片描述
  • toJavaObject方法 : JSON对象转为Java对象 在这里插入图片描述
  • public static String toJSONStringWithDateFormat(Object object, String dateFormat,SerializerFeature… features)
    @Test
    public void testDateFormart() {
        String dateStr = JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd");
        System.out.println(dateStr); // "2022-08-15"
    }
    
JSONObject类常用方法

public class JSONObject extends JSON implements Map, Cloneable, Serializable, InvocationHandler

  • 由于JSONObject继承JSON类, 所以JSON抽象类的公共方法也能够使用
  • 还继承了Map, 也拥有Map的一些方法
  • public JSONObject getJSONObject(int index) : 根据JSONArray的索引index, 生成JSONObject对象

  • public JSONArray getJSONArray(int index) : 根据JSONArray的索引index, 生成JSON类型的数组

  • public T getXxx(int index) : 根据JSONArray的index, 获取该index的value 在这里插入图片描述

JSONArray类常用方法

public class JSONArray extends JSON implements List, Cloneable, RandomAccess, Serializable

  • 由于JSONArray继承JSON类, 所以JSON抽象类的公共方法也能够使用
  • 也继承了List接口, 拥有List的一些方法
  • public JSONObject getJSONObject(String key) : 根据JSON的key, 生成JSONObject对象

  • public JSONArray getJSONArray(String key) : 根据JSON的key, 生成JSON类型的数组

  • public T getXxx(String key) : 根据JSON的key, 获取该key的value 在这里插入图片描述

FastJson的使用 FastJson序列化API

序列化 : 把Java对象转换为字节序列(JSON字符串)的过程。

在这里插入图片描述

  • JSON.toJSONString

    • 序列化Java对象
    public void objectToJson(){
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        student.setAge(20);
        student.setAddress("北京市");
        student.setEmail("zs@sina.com");
        String jsonString = JSON.toJSONString(student);
        System.out.println(jsonString);
    }
    
    • 序列化List集合
    public void listToJson(){
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        student.setAge(20);
        student.setAddress("北京市");
        student.setEmail("zs@sina.com");
    
        Student student2 = new Student();
        student2.setId(2);
        student2.setName("张三2");
        student2.setAge(22);
        student2.setAddress("北京市2");
        student2.setEmail("zs2@sina.com");
    
        List list = new ArrayList();
        list.add(student);
        list.add(student2);
        String jsonString = JSON.toJSONString(list);
        System.out.println(jsonString);
    }
    
    • 序列化Map集合
    public void mapToJson(){
        Student student = new Student();
        student.setId(1);
        student.setName("张三");
        student.setAge(20);
        student.setAddress("北京市");
        student.setEmail("zs@sina.com");
    
        Student student2 = new Student();
        student2.setId(2);
        student2.setName("张三2");
        student2.setAge(22);
        student2.setAddress("北京市2");
        student2.setEmail("zs2@sina.com");
        Map map = new HashMap();
        map.put("s1",student);
        map.put("s2",student2);
        String jsonString = JSON.toJSONString(map);
        System.out.println(jsonString);
    }
    
FashJson反序列化API

反序列化: 把字节序列(JSON字符串)恢复为Java对象的过程

在这里插入图片描述

  • JSON.parseObject

    • 反序列化Java对象
    public void jsonToObject(){
        String jsonString = "{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"}";
        Student student = JSON.parseObject(jsonString, Student.class);
        System.out.println(student);
    }
    
  • JSON.parseArray

    • 反序列化List集合
    public void jsonToList(){
        String jsonString = "[{\"address\":\"北京市\",\"age\":20,\"email\":\"zs@sina.com\",\"id\":1,\"name\":\"张三\"},{\"address\":\"北京市2\",\"age\":22,\"email\":\"zs2@sina.com\",\"id\":2,\"name\":\"张三2\"}]";
        List list = JSON.parseArray(jsonString,Student.class);
        for (int i = 0; i JSON串

    String jsonStr = JSONObject.toJSONString(Java对象实例)

    @Test
    public void javaObj2JsonStr() {
        Student student = Student.builder().name("lucky").age(22).build();
        //String jsonString = JSON.toJSONString(student);
        String jsonString = JSONObject.toJSONString(student);
        System.out.println(jsonString); // {"age":22,"name":"lucky"}
    }
    

    Java对象–>JSON对象

    JSONObject jsonObj = (JSONObject) JSONObject.toJSON(Java对象实例)

    @Test
    public void javaObj2JsonObj() {
        Student student = Student.builder().name("lucky").age(22).build();
        Object obj = JSONObject.toJSON(student);
        JSONObject jsonObject = (JSONObject) obj;
        System.out.println(jsonObject); // {"name":"lucky","age":22}
        
        String name = jsonObject.getString("name");
        Integer age = jsonObject.getInteger("age");
        System.out.printf("name: %s, age: %d", name, age); // name: lucky, age: 22
    }
    
    JSON串 转 Java对象、JSON对象

    JSON串–>Java对象

    T obj = JSONObject.parseObject(JSON字符串, Java对象.class);

    @Test
    public void jsonStr2JavaObj() {
        String stuStr = "{\"age\":22,\"name\":\"lucky\"}";
        Student student = JSONObject.parseObject(stuStr, Student.class);
        System.out.println(student); // Student(name=lucky, age=22)
    }
    

    JSON串–>JSON对象

    JSONObject jsonObj = JSONObject.parseObject(JSON字符串)

    @Test
    public void jsonStr2JsonObj() {
    	String stuStr = "{\"age\":22,\"name\":\"lucky\"}";
        JSONObject jsonObject = JSONObject.parseObject(stuStr);
        System.out.println(jsonObject); // {"name":"lucky","age":22}
    
        String name = jsonObject.getString("name");
        Integer age = jsonObject.getInteger("age");
        System.out.printf("name: %s, age: %d", name, age); // name: lucky, age: 22
    }
    
    JSON对象 转 Java对象、JSON串

    JSON对象–>Java对象

    T obj = JSONObject.toJavaObject(JSON对象实例, Java对象.class);

    @Test
    public void jsonObj2JavaObj() {
        Student student = Student.builder().name("lucky").age(22).build();
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(student);
        Student stu2 = jsonObject.toJavaObject(Student.class);
        System.out.println(stu2); // Student(name=lucky, age=22)
    }
    

    JSON对象–>JSON串

    String jsonStr = JSONObject.toJSONString();

    @Test
    public void jsonObj2JsonStr() {
        Student student = Student.builder().name("lucky").age(22).build();
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(student);
        String jsonStr = jsonObject.toJSONString();
        System.out.println(jsonStr); // {"age":22,"name":"lucky"}
    }
    
    JSON字符串 转 List

    List parseArray(JSON字符串, Java对象.class)

    @Test
    public void jsonStr2List() {
        String jsonStr = "[{\"name\":\"lucky\",\"age\":22}, {\"name\":\"Tom\",\"age\":33}]";
        List students = JSONObject.parseArray(jsonStr, Student.class);
        students.forEach(System.out::println);
        /*
            输出
            Student(name=lucky, age=22)
            Student(name=Tom, age=33)
         */
    }
    
    JSON字符串 转 Map

    Map mapObj = JSONObject.parseObject(jsonStr, new TypeReference() { })

    @Test
    public void jsonStr2Map() {
        Map map = new HashMap() {{
            put("name", "lucky");
            put("age", "22");
        }};
    
        String mapStr = JSONObject.toJSONString(map);
        System.out.println(mapStr); // {"name":"lucky","age":"22"}
    
      //Map mapObj = (Map) JSON.parse(mapStr)
        Map mapObj = JSONObject.parseObject(mapStr, new TypeReference() {
        });
        System.out.println(mapObj); // {name=lucky, age=22}
    }
    

    泛型反序列化

    • import com.alibaba.fastjson.TypeReference;
    • List list = JSON.parseObject("...", new TypeReference() {});
    SerializerFeature枚举

    该枚举支持序列化的一些特性数据定义:

    • 枚举常量 WriteMapNullValue 序列化为null的字段
    • 枚举常量 WriteNullStringAsEmpty 字段为null,序列化为""
    • 枚举常量 WriteNullNumberAsZero 字段为null,序列化为0
    • 枚举常量 PrettyFormat格式化输出
    • 枚举常量 WriteNullBooleanAsFalse 字段值为null 输出false
    • 枚举常量 WriteDateUseDateFormat 格式化日期格式
    // 测试类
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        private String name;
        private Integer age;
        private String address;
    }
    

    测试

    public class JSONFieldTest {
    
        @Test
        public void testSerializerFeature() {
            Student stu = Student.builder().age(20).address("上海").build();
            String stuJson = JSON.toJSONString(stu);
            System.out.println("stuJson = " + stuJson); // stuJson = {"address":"上海","age":20}
    
            String stuJson2 = JSON.toJSONString(stu, SerializerFeature.WriteMapNullValue);
            System.out.println("stuJson2 = " + stuJson2); // stuJson2 = {"address":"上海","age":20,"name":null}
    
            String stuJson3 = JSON.toJSONString(stu, SerializerFeature.WriteNullStringAsEmpty);
            System.out.println("stuJson3 = " + stuJson3); // stuJson3 = {"address":"上海","age":20,"name":""}
    
            Student stu2 = Student.builder().name("lucky").address("上海").build();
            String stu2Json = JSON.toJSONString(stu2, SerializerFeature.WriteNullNumberAsZero);
            System.out.println("stu2Json = " + stu2Json); // stu2Json = {"address":"上海","age":0,"name":"lucky"}
    
            String stu2Json2 = JSON.toJSONString(stu2, SerializerFeature.PrettyFormat);
            System.out.println("stu2Json = " + stu2Json2);
            
            // 输出
            /*
                stuJson = {"address":"上海","age":20}
                stuJson2 = {"address":"上海","age":20,"name":null}
                stuJson3 = {"address":"上海","age":20,"name":""}
                stu2Json = {"address":"上海","age":0,"name":"lucky"}
                stu2Json = {
                    "address":"上海",
                    "name":"lucky"
                }
             */
        }
    }
    
    @JSONField注解

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

    该注解作用于方法上,字段上和参数上, 可在序列化和反序列化时进行特性功能定制.

    • 注解属性 : name 序列化后的名字
    • 注解属性 : ordinal序列化后的顺序
    • 注解属性 : format 序列化后的格式, 对日期格式有用
    • 注解属性 : serialize 是否序列化该字段
    • 注解属性 : deserialize 是否反序列化该字段
    • 注解属性 : serialzeFeatures 序列化时的特性定义
    1. @JSONField配置方式, 使用name属性

    可以配置在Field上, 或者getter/setter方法上

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        @JSONField(name = "NAME")
        private String name;
        private Integer age;
    }
    

    测试

    @Test
    public void testJSONFieldName() {
        Student stu = Student.builder().name("lucky").age(20).build();
        // 序列化后的JSON中key的名字
        String stuStr = JSON.toJSONString(stu);
        System.out.println("stuStr = " + stuStr); // stuStr = {"NAME":"lucky","age":20}
    
        // 通过@FieldName(name="xxx"),可以将JSON串中xxx,反序列化给标注注解的字段
        Student stuObj = JSONObject.parseObject(stuStr, Student.class);
        System.out.println("stuObj = " + stuObj); // stuObj = Student(name=lucky, age=20)
    }
    
    //输出:
    //stuStr = {"NAME":"lucky","age":20}
    //stuObj = Student(name=lucky, age=20)
    
    2. 使用format配置日期格式化
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
          // 配置date序列化和反序列使用yyyy-MM-dd日期格式
          @JSONField(format="yyyy-MM-dd")
          private Date date;
     }
    

    测试

    @Test
    public void testJSONFieldFormat() {
        Student stu = Student.builder().date(new Date()).build();
        String jsonStu = JSONObject.toJSONString(stu);
        System.out.println("jsonStu = " + jsonStu); // jsonStu = {"date":"2022-08-15"}
    }
    
    //输出
    //jsonStu = {"date":"2022-08-15"}
    
    3. 使用serialize/deserialize指定字段是否序列化
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        // 不进行反序列化
        @JSONField(name = "NAME", deserialize = false)
        private String name;
    
        // 不进行序列化
        @JSONField(name = "AGE", serialize = false)
        private Integer age;
    
        @JSONField(format = "yyyy/MM/dd")
        private Date date;
    }
    

    测试

    @Test
    public void testIsSerializeAndDeSerialize() {
        Student stuObj = Student.builder().name("lucky").age(22).date(new Date()).build();
        String stuJson = JSONObject.toJSONString(stuObj);
        System.out.println("stuJson = " + stuJson); // stuJson = {"NAME":"lucky","date":"2022/08/16"}
    
        Student stuObj2 = JSON.parseObject(stuJson, Student.class);
        System.out.println("stuObj2 = " + stuObj2);
    }
    
    //输出:
    //stuJson = {"NAME":"lucky","date":"2022/08/16"}
    //stuObj2 = Student(name=null, age=null, date=Tue Aug 16 00:00:00 CST 2022)
    
    4. 使用ordinal指定字段的顺序 (序列化)

    缺省fastjson序列化一个java bean,是根据FieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本。

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        @JSONField(name = "NAME")
        private String name;
        @JSONField(name = "AGE")
        private Integer age;
        private Double salary;
    }
    

    测试

    @Test
    public void testJSONFieldOrdinal() {
        Student stuObj = Student.builder().name("lucky").age(22).salary(999D).build();
        // 正常字段的序列化顺序(根据字段首字母的顺序)
        String stuJson = JSON.toJSONString(stuObj);
        System.out.println("stuJson = " + stuJson); // stuJson = {"AGE":22,"NAME":"lucky","salary":999.0}
    
        Student stu = JSON.parseObject(stuJson, Student.class);
        System.out.println("stu = " + stu); // stu = Student(name=lucky, age=22, salary=999.0)
    
        // 输出
        // stuJson = {"AGE":22,"NAME":"lucky","salary":999.0}
        // stu = Student(name=lucky, age=22, salary=999.0)
    }
    

    使用ordinal属性

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        @JSONField(name = "NAME", ordinal = 2)
        private String name;
        @JSONField(name = "AGE", ordinal = 1)
        private Integer age;
        @JSONField(ordinal = 0)
        private Double salary;
    }
    

    测试

    @Test
    public void testJSONFieldOrdinal() {
        Student stuObj = Student.builder().name("lucky").age(22).salary(999D).build();
        // 正常字段的序列化顺序(根据字段首字母的顺序)
        String stuJson = JSON.toJSONString(stuObj);
        System.out.println("stuJson = " + stuJson); 
    
        Student stu = JSON.parseObject(stuJson, Student.class);
        System.out.println("stu = " + stu); 
    
        // 输出
        //stuJson = {"salary":999.0,"AGE":22,"NAME":"lucky"}
        //stu = Student(name=lucky, age=22, salary=999.0)
    }
    
    5. 使用serializeUsing制定属性的序列化类

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

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        @JSONField(serializeUsing = CustomedSalarySerializer.class)
        private Double salary;
    }
    
    public class CustomedSalarySerializer implements ObjectSerializer {
        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
            Double salary = (Double) object;
            String salaryStr = salary + "元";
            serializer.write(salaryStr);
        }
    }
    

    测试代码

    @Test
    public void testJSONFieldSerializeUsing() {
        Student stuObj = Student.builder().salary(999.2D).build();
        String stuJson = JSONObject.toJSONString(stuObj);
        System.out.println("stuJson = " + stuJson);
        
        // 输出
        // stuJson = {"salary":"999.2元"}
    }
    
    6. JSONField alternateNames

    在fastjson在1.2.21版本中提供了一个借鉴自gson的特性,支持反序列化时使用多个不同的字段名称,使用的方式是配置JSONField的alternateNames。

    @Data
    @NoArgsConstrustor
    @AllArgsConstrustor
    public class Student {
        private int id;
    
        @JSONField(alternateNames = {"user", "person"})
        private String name;
    }
    

    测试

    @Test
    public void testJSONFieldAlternateNames() {
        String jsonVal0 = "{\"id\":5001,\"name\":\"Jobs\"}";
        String jsonVal1 = "{\"id\":5382,\"user\":\"Mary\"}";
        String jsonVal2 = "{\"id\":2341,\"person\":\"Bob\"}";
    
        Student obj0 = JSON.parseObject(jsonVal0, Student.class);
    
        Assert.assertEquals(5001, obj0.getId());
        Assert.assertEquals("Jobs", obj0.getName()); // true
    
        Student obj1 = JSON.parseObject(jsonVal1, Student.class);
        Assert.assertEquals(5382, obj1.getId());
        Assert.assertEquals("Mary", obj1.getName()); // true
    
        Student obj2 = JSON.parseObject(jsonVal2, Student.class);
        Assert.assertEquals(2341, obj2.getId());
        Assert.assertEquals("Bob", obj2.getName()); // true
    }
    
    7. JSONField jsonDirect

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

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
    
        private int id;
    
        @JSONField(jsonDirect = true)
        private String other;
    }
    

    测试

    @Test
    public void testJSONFieldJsonDirect() {
        Student stu = Student.builder().id(1001).other("{\"name\":\"lucky\"}").build();
        String stuJSON = JSON.toJSONString(stu);
        System.out.println("stuJSON = " + stuJSON);
    
        // 不加 @JSONField(jsonDirect = true) 输出: stuJSON = {"id":1001,"other":"{\"name\":\"lucky\"}"}
        // 加 @JSONField(jsonDirect = true) 输出: stuJSON = {"id":1001,"other":{"name":"lucky"}}
    }
    
    @ JSONType注解

    该注解作用于类上 , 对该类的字段进行序列化和反序列化时的特性功能定制.

    • 注解属性 : includes 要被序列化的字段.
    • 注解属性 : ignores 不要被序列化的字段.
    • 注解属性 : orders 序列化后的顺序.
    • 注解属性 : serialzeFeatures 序列化时的特性定义.
    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    @JSONType(includes = {"name", "sex"})  //序列化只序列化这两个属性成员变量
    public class Student {
    
        private int id;
        private String name;
        private String sex;
        private String password;
        private String phone;
    }
    
    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    @JSONType(ignores = {"id", "sex"})  //不序列化这两个成员变量
    public class Student2 {
        private int id;
        private String name;
        private String sex;
        private String password;
        private String phone;
    }
    

    测试

    @Test
    public void testFieldType() {
        Student stu1 = new Student();
        stu1.setId(11).setName("名字1").setPassword("123456").setPhone("13502141419").setSex("男");
        String stuJson1 = JSON.toJSONString(stu1);
        System.out.println("stuJson1 = " + stuJson1);
    
        Student2 stu2 = new Student2();
        stu2.setId(11).setName("名字1").setPassword("123456").setPhone("13502141419").setSex("男");
        String stuJson2 = JSON.toJSONString(stu2);
        System.out.println("stuJson2 = " + stuJson2);
    
        // 输出
        // stuJson1 = {"name":"名字1","sex":"男"}
        // stuJson2 = {"name":"名字1","password":"123456","phone":"13502141419"}
    }
    
关注
打赏
1661428283
查看更多评论
0.0434s