• 【json的处理】三、FastJson的处理


    目前处理json的方法有很多,这里主要总结四种方法

    1. Gson方式处理json 【json的处理】一、Gson处理

    2. FastJson方式处理json 【json的处理】三、FastJson的处理

    3. Jackson方式处理json 【json的处理】二、Jackson的处理

    4. json-flattener方式处理json 【json的处理】四、json-flattener的处理

    本文主要介绍FastJson的方式

    前言:

    下面主要通过几个方面来介绍fastjson:

    1. JsonObject

    2. JsonArray

    3. JsonObject+JsonArray

    首先先介绍一下两个容易混淆的概念:

    1. json对象:用 { } 表示的

      例:{ "id":"123", "name":"张三", "age":"11"}

    2. json数组:由多个json对象组成,用 [ ] 表示的

      例:[{ "id":"123", "name":"张三", "age":"11"},{ "id":"321", "name":"李四", "age":"21"}]

    需要引入依赖

    <!-- fastjson的依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.44</version>
    </dependency>

    一、JsonObject

    这里先提及两个概念:

    序列化:json对象转字符串

    反序列化:字符串转json对象

    1. 基本用法

    //定义一个json对象用来演示
    String str = "{ "id":"123", "name":"张三", "age":"11"}";
    //【字符串转json对象】
    JSONObject jsonObject = JSONObject.parseObject(str);
    //【json对象转字符串】
    String strTemp = jsonObject.toJSONString();
    //【json对象中是否包含某个key】
    boolean isHasKey = jsonObject.containsKey("na");
    //【json对象中是否包含某个值】
    boolean isHasValue = jsonObject.containsValue("123");
    //【获取json对象中某个键对应的值】
    Object id = jsonObject.get("id");
    //【json对象转set】
    Set<Map.Entry<String, Object>> entries = jsonObject.entrySet();
    //【json对象转Map】
    Map<String, String> params = JSONObject.parseObject(jsonObject.toJSONString(), new TypeReference<Map<String, String>>(){});
    //【Map转json对象】
    String jsonStr_Map = JSONUtils.toJSONString(params);
    JSONObject jsonObjectTemp = JSONObject.parseObject(jsonStr_Map);
    //【遍历json对象中的所有键值对】
    for (Map.Entry<String,Object> entry : jsonObject.entrySet()){
        String key = entry.getKey();
        Object value = entry.getValue();
        System.out.println("key="+key+" value="+value);
    }

    2. 高级用法

    2.1 实体类与json之间的转换

    //实体类
    @Data
    @AllArgsConstructor
    public class TestUser {
        private String name;
        private Integer age;
        private Integer sex;
    }
    
    //测试类
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser("111",11,1);
    //【实体类转json】
    JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
    //结果:{"sex":1,"name":"111","age":11}
    System.out.println(jsonObj);
    //【json转实体类】 反序列化
    TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
    //结果:TestUser(name=111, age=11, sex=1)
    System.out.println(testUserTemp);
    
    //这里补充一个  list对象转json 
    //如果有值为null,会导致这个key都被默认去掉,需要加上SerializerFeature.WriteMapNullValue 
    List<User> list = new ArrayList<>();
    JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list,SerializerFeature.WriteMapNullValue))
    名称含义
    QuoteFieldNames 输出key时是否使用双引号,默认为true
    UseSingleQuotes 使用单引号而不是双引号,默认为false
    WriteMapNullValue 是否输出值为null的字段,默认为false
    WriteEnumUsingToString Enum输出name()或者original,默认为false
    UseISO8601DateFormat Date使用ISO8601格式输出,默认为false
    WriteNullListAsEmpty List字段如果为null,输出为[],而非null
    WriteNullStringAsEmpty 字符类型字段如果为null,输出为”“,而非null
    WriteNullNumberAsZero 数值字段如果为null,输出为0,而非null
    WriteNullBooleanAsFalse Boolean字段如果为null,输出为false,而非null
    SkipTransientField 如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true
    SortField 按字段名称排序后输出。默认为false
    WriteTabAsSpecial 把 做转义输出,默认为false 不推荐
    PrettyFormat 结果是否格式化,默认为false
    WriteClassName 序列化时写入类型信息,默认为false。反序列化是需用到
    DisableCircularReferenceDetect 消除对同一对象循环引用的问题,默认为false
    WriteSlashAsSpecial 对斜杠’/’进行转义
    BrowserCompatible 将中文都会序列化为uXXXX格式,字节数会多一些,但是能兼容IE6,默认为false
    WriteDateUseDateFormat 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj,SerializerFeature.WriteDateUseDateFormat);
    DisableCheckSpecialChar 一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
    NotWriteRootClassName 含义
    BeanToArray 将对象转为array输出
    WriteNonStringKeyAsString 含义
    NotWriteDefaultValue 含义
    BrowserSecure 含义
    IgnoreNonFieldGetter 含义
    WriteEnumUsingName 含义

    2.2 JSONField注解

    那么如果我想要在实体类转json的时候,排除掉某些字段该怎么做呢?

    答案:

    使用@JSONField(serialize = false) 注解。

    (是否参与序列化,false代表该字段不输出,但是如果加了final,这个字段就无法被过滤)

    修改后的效果如下:

    @Data
    @AllArgsConstructor
    public class TestUser {
        @JSONField(serialize = false)
        private String name;
        private Integer age;
        private Integer sex;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser("111",11,1);
    //【实体类转json】
    JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
    //结果:{"sex":1,"age":11}
    System.out.println(jsonObj);
    //【json转实体类】 反序列化
    TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
    //结果:TestUser(name=null, age=11, sex=1)
    System.out.println(testUserTemp);

    那么如果我想要在实体类转json的时候,不使用实体类中的名称该如何做呢?

    答案:

    使用@JSONField(name = "别名") 注解。

    使用字段别名,效果如下:

    @Data
    @AllArgsConstructor
    public class TestUser {
        @JSONField(name = "t_name")
        private String name;
        private Integer age;
        private Integer sex;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser("111",11,1);
    //【实体类转json】
    JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
    //结果:{"t_name":"111","sex":1,"age":11}
    System.out.println(jsonObj);
    //【json转实体类】 反序列化
    TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
    //结果:TestUser(name=111, age=11, sex=1)
    System.out.println(testUserTemp);

    那么如果现在有个时间类型的字段,我想要以固定的格式输出,该怎么办呢?

    答案:

    使用@JSONField(format="yyyy-MM-dd HH:mm:ss") 注解。

    下面先添加一个时间字段date,看看添加前后的效果:

    @Data
    @AllArgsConstructor
    public class TestUser {
        private String name;
        private Integer age;
        private Integer sex;
        @JSONField(format="yyyy-MM-dd HH:mm:ss")
        private Date date;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser("111",11,1,new Date());
    //【实体类转json】
    JSONObject jsonObj = (JSONObject)JSONObject.toJSON(testUser);
    //添加前结果:{"date":1600485884579,"sex":1,"name":"111","age":11}
    //添加后结果:{"date":"2020-09-19 11:25:46","sex":1,"name":"111","age":11}
    System.out.println(jsonObj);
    //【json转实体类】 反序列化
    TestUser testUserTemp = JSONObject.parseObject(jsonObj.toJSONString(), TestUser.class);
    //添加前结果:TestUser(name=111, age=11, sex=1, date=Sat Sep 19 11:24:44 CST 2020)
    //添加后结果:TestUser(name=111, age=11, sex=1, date=Sat Sep 19 11:25:46 CST 2020)
    System.out.println(testUserTemp);

    那么如果某个字段的值是null,在序列化的时候,可以看到生成的字符串中没有对应的key,那么我想要实现,如果值为空,给其一个默认值:

    这里要提及一个知识:SerializerFeature属性,下面列举几个,详细的可以去查api

    参考:https://www.cnblogs.com/wbxk/p/10064737.html

    1. 字符类型字段如果为null,输出为"",而非null WriteNullStringAsEmpty

    2. 数值字段如果为null,输出为0,而非null WriteNullNumberAsZero

    3. Boolean字段如果为null,输出为false,而非null WriteNullBooleanAsFalse

    4. List字段如果为null,输出为[],而非null WriteNullListAsEmpty

    @Data
    @AllArgsConstructor
    public class TestUser {
        @JSONField(serialzeFeatures=SerializerFeature.WriteNullStringAsEmpty)
        private String name;
        private Integer age;
        private Integer sex;
        @JSONField(format="yyyy-MM-dd HH:mm:ss")
        private Date date;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser(null,11,1,new Date());
    String jsonStr = JSON.toJSONString(testUser);
    //加注解前:{"age":11,"date":"2020-09-19 12:49:07","sex":1}
    //加注解后:{"age":11,"date":"2020-09-19 12:48:28","name":"","sex":1}
    System.out.println(jsonStr);

    现在想要将json对象转换成实体类对象,方法如下:

    @Data
    public class TestUser {
        private String name;
        private Integer age;
        private Integer sex;
        private Date date;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser();
    testUser.setName("11");
    testUser.setAge(11);
    testUser.setSex(1);
    String jsonStr = JSON.toJSONString(testUser);
    //实体类转成json对象
    JSONObject jsonObject = JSONObject.parseObject(jsonStr);
    //【json对象转成实体类】
    TestUser testUserTemp = JSON.toJavaObject(jsonObject, TestUser.class);
    //结果:TestUser(name=11, age=11, sex=1, date=null)
    System.out.println(testUserTemp);

    这里要注意:上面的例子里我都是用的@AllArgsConstructor来方便我创建实体类数据,但是我发现如果加上了这个注解,在使用toJavaObject方法的时候会报错。不使用这个注解没有问题。报错信息如下:

    网上搜的结果为:

    实体类中存在内嵌的其它类,将内部类修改为静态内部类即可,但是我这里也没有发现有内部类的字段,于是我尝试将Date类型的屏蔽,结果成功了,暂时还没有想清楚是什么问题

    //报错代码如下
    @Data
    @AllArgsConstructor
    public class TestUser {
        private String name;
        private Integer age;
        private Integer sex;
        private Date date;
    }
    
    //定义一个实体类对象用来演示
    TestUser testUser = new TestUser("111",11,1,new Date());
    String jsonStr = JSON.toJSONString(testUser);
    JSONObject jsonObject = JSONObject.parseObject(jsonStr);
    TestUser testUserTemp = JSON.toJavaObject(jsonObject, TestUser.class);

    二、 JsonArray

    JsonArray:即json数组,由多个json对象(jsonObject)组成

    //定义一个json数组类型的字符串用来演示
    String jsonstr = "[{"sex":"1","name":"111","age":"11"},{"sex":"0", "name":"222","age":"21"}]";
    //【String转jsonArray】
    JSONArray jsonArray = JSONArray.parseArray(jsonstr);
    //【jsonArray转String】
    String jsonstrTemp = JSON.toJSONString(jsonArray);
    //【jsonArray转list】
    List list = JSONObject.parseArray(jsonArray.toJSONString());
    //【jsonArray转list-->对象】
    List<TestUser> testUsers = JSONObject.parseArray(jsonArray.toJSONString(), TestUser.class);
    //【list转jsonArray】
    List listTemp = new ArrayList();
    JSONArray array = JSONArray.parseArray(JSON.toJSONString(listTemp));
    //【list转jsonArray--->对象】
    List<TestUser> testUserList = new ArrayList<>();
    JSONArray array1 = JSONArray.parseArray(JSON.toJSONString(listTemp));
    //【String转List】
    List<TestUser> testUserList1 = JSONObject.parseArray(jsonstr, TestUser.class);
    //【循环获取jsonArray中所有的jsonObject】
    for (int i = 0; i < jsonArray.size(); i++) {
        JSONObject jsonObject = jsonArray.getJSONObject(i);
        String id = jsonObject.getString("sex");
        String name = jsonObject.getString("name");
        //这里要注意:age字段也可以用getString方法来获取
        Integer age = jsonObject.getInteger("age");
    }

    三、JsonObject+JsonArray

    如何判断一个不确定格式的json串,每个key对应的类型呢?

    //【判断json类型】
    String text0 = "11";
    String text2 = "{ "sex":"1", "name":"张三", "age":"11"}";
    String text3 = "[{ "sex":"1", "name":"张三", "age":"11"},{ "sex":"0", "name":"李四", "age":"21"}]";
    
    Object parse0 = JSON.parse(text0);
    System.out.println(parse0 instanceof java.lang.Integer);//true
    
    Object parse2 = JSON.parse(text2);
    System.out.println(parse2 instanceof JSONObject);//true
    
    Object parse3 = JSON.parse(text3);
    System.out.println(parse3 instanceof JSONArray);//true

    持续更新!!!

  • 相关阅读:
    css技巧和经验列表
    CSS3嵌入字体@font-face调用字体
    新闻列表单行滚动(多行显示)简洁向上滚动js效果
    打破构图的平衡!增强设计感染力
    何以双十(补昨天)
    MySQL5.7 基于二进制包的安装
    Nginx Log日志统计分析常用命令
    MySQL错误代码大全
    MVC4中的Display Mode简介
    ReadOnly关键字修饰的变量可以修改,只是不能重新分配
  • 原文地址:https://www.cnblogs.com/flyinghome/p/14637062.html
Copyright © 2020-2023  润新知