java:json操作一、fastjon

java:json操作一、fastjon

1 依赖配置

在https://search.maven.org/搜索fastjson,依赖如下:

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

前言:

序列化和反序列化:网络传输时,使用的是Byte进行传输,速度、效率会更好。将对象转换成Byte,就是序列化;反之,将Byte转换成对象,就是反序列化。Json的序列化,即是将对象转换成json字符串;反序列化,就是将json字符串转换成对象。

2 使用

2.1 序列化
在这里插入图片描述
在这里插入图片描述
(1)序列化及null值属性的展示:

UseFastJson:

package com.xiaoxu.json.core;

import com.alibaba.fastjson.JSON;
import com.xiaoxu.json.vo.Drinks;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.core.UseFastJson
 */
@Service
public class UseFastJson {
    public void toJson(Drinks d){
        String s = JSON.toJSONString(d);
        System.out.println("Drinks的对象转为JSON字符串:"+s);
    }
    public Drinks buildDrinks(){
        Drinks d = new Drinks();
        d.setDrinkId(123L);
        d.setDrinkName("东鹏特饮");
        d.setProduceDate(new Date());
        d.setSaleDate(LocalDateTime.now());
        return d;
    }
}

Drinks:

package com.xiaoxu.json.vo;

import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.vo.Drinks
 */
@Data
public class Drinks {
    /*
    * 饮料id
    * */
    long drinkId;
    /*
    * 饮料名称
    * */
    String drinkName;
    /*
    * 生产地址
    * */
    String produceAddress;
    /*
    * 生产日期
    * */
    Date produceDate;
    /*
    * 销售日期
    * */
    LocalDateTime saleDate;
}

TestFastJson:

package json;

import com.xiaoxu.boot.MainApplication;
import com.xiaoxu.json.core.UseFastJson;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestFastJson
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class TestFastJson {
    @Autowired
    UseFastJson u;

    @Test
    public void test_01(){
        u.toJson(u.buildDrinks());
    }
}

结果:

Drinks的对象转为JSON字符串:{"drinkId":123,"drinkName":"东鹏特饮","produceDate":1646283066154,"saleDate":"2022-03-03T12:51:06.158"}

可见,对象中缺少了produceAddress,希望null值也可以打印出来,修改如下:

public void toJson(Drinks d){
    String s = JSON.toJSONString(d, SerializerFeature.WriteMapNullValue);
    System.out.println("Drinks的对象转为JSON字符串:"+s);
}

重新执行:

Drinks的对象转为JSON字符串:{"drinkId":123,"drinkName":"东鹏特饮","produceAddress":null,"produceDate":1646283485906,"saleDate":"2022-03-03T12:58:05.910"}

(2)日期时间的格式化:

修改需序列化的pojo:

package com.xiaoxu.json.vo;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.vo.Drinks
 */
@Data
public class Drinks {
    /*
    * 饮料id
    * */
    long drinkId;
    /*
    * 饮料名称
    * */
    String drinkName;
    /*
    * 生产地址
    * */
    String produceAddress;
    /*
    * 生产日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    Date produceDate;
    /*
    * 销售日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    LocalDateTime saleDate;
}

执行结果如下:

Drinks的对象转为JSON字符串:{"drinkId":123,"drinkName":"东鹏特饮","produceAddress":null,"produceDate":"2022-03-03 13:02:39","saleDate":"2022-03-03 13:02:39"}

(3)fastJson之引用探测:

修改UseFastJson:

package com.xiaoxu.json.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xiaoxu.json.vo.Drinks;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.core.UseFastJson
 */
@Service
public class UseFastJson {
    public void toJson(Object d){
        String s = JSON.toJSONString(d, SerializerFeature.WriteMapNullValue);
        System.out.println("Drinks的对象转为JSON字符串:"+s);
    }
    public Drinks buildDrinks(){
        Drinks d = new Drinks();
        d.setDrinkId(123L);
        d.setDrinkName("东鹏特饮");
        d.setProduceDate(new Date());
        d.setSaleDate(LocalDateTime.now());
        return d;
    }
}

增加单测test_02:

package json;

import com.xiaoxu.boot.MainApplication;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestFastJson
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class TestFastJson {
    @Autowired
    UseFastJson u;

    @Test
    public void test_01(){
        u.toJson(u.buildDrinks());
    }

    @Test
    public void test_02(){
        Drinks drinks = u.buildDrinks();
        List<Drinks> l = new ArrayList<Drinks>(){{
            for (int i = 0; i < 3; i++) {
                add(drinks);
            }
        }};
        u.toJson(l);
    }
}

执行test_02:

Drinks的对象转为JSON字符串:[{"drinkId":123,"drinkName":"东鹏特饮","produceAddress":null,"produceDate":"2022-03-03 13:06:35","saleDate":"2022-03-03 13:06:35"},{"$ref":"$[0]"},{"$ref":"$[0]"}]

$ref就是fastJson的引用探测,对于同一个引用对象(地址相同),那么fastjson打印出来的list集合就会包含: $ref。
取消引用探测如下修改:

public void toJson(Object d){
    String s = JSON.toJSONString(d, SerializerFeature.DisableCircularReferenceDetect);
    System.out.println("Drinks的对象转为JSON字符串:"+s);
}

再次执行:

Drinks的对象转为JSON字符串:[{"drinkId":123,"drinkName":"东鹏特饮","produceDate":"2022-03-03 13:10:39","saleDate":"2022-03-03 13:10:39"},{"drinkId":123,"drinkName":"东鹏特饮","produceDate":"2022-03-03 13:10:39","saleDate":"2022-03-03 13:10:39"},{"drinkId":123,"drinkName":"东鹏特饮","produceDate":"2022-03-03 13:10:39","saleDate":"2022-03-03 13:10:39"}]

(4)filter定制处理:

增加单测test_03:

package json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xiaoxu.boot.MainApplication;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestFastJson
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class TestFastJson {
    @Autowired
    UseFastJson u;

    @Test
    public void test_01(){
        u.toJson(u.buildDrinks());
    }

    @Test
    public void test_02(){
        Drinks drinks = u.buildDrinks();
        List<Drinks> l = new ArrayList<Drinks>(){{
            for (int i = 0; i < 3; i++) {
                add(drinks);
            }
        }};
        u.toJson(l);
    }

    @Test
    public void test_03(){
        NameFilter nameFilter = (o, name, value) -> {
            //o是整个Drinks对象(u.buildDrinks()),name是成员变量名称,value是其set对应的值
            return name.toUpperCase(Locale.ROOT);
        };
        System.out.println(JSON.toJSONString(u.buildDrinks(), nameFilter, SerializerFeature.WriteMapNullValue));
    }
}

执行test_03:

{"DRINKID":123,"DRINKNAME":"东鹏特饮","PRODUCEADDRESS":null,"PRODUCEDATE":1646284560146,"SALEDATE":"2022-03-03T13:16:00.170"}

json字符串的对象的成员变量key,全部改为了大写。

2.2 反序列化

(1)json字符串转为Drinks对象:
在这里插入图片描述
在这里插入图片描述
这里使用:

package json;

import com.alibaba.fastjson.JSON;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestContraryFastJSon
 */
public class TestContraryFastJSon {
    @Autowired
    UseFastJson useFastJson;

    @Test
    public void test_01(){
        String a = "{\"drinkId\":123,\"drinkName\":\"东鹏特饮\",\"produceDate\":\"2022-03-03 13:31:13\",\"saleDate\":\"2022-03-03 13:31:13\"}";
        Drinks drinks = JSON.parseObject(a, Drinks.class);
        System.out.println(drinks);
    }
}

执行结果如下:

Drinks(drinkId=123, drinkName=东鹏特饮, produceAddress=null, produceDate=Thu Mar 03 13:31:13 CST 2022, saleDate=2022-03-03T13:31:13)

(2)反序列化的泛型处理:

泛型结果如下:

package json;

import lombok.Data;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.BaseResult
 */
@Data
public class BaseResult<T> {
    private boolean isSuccess = Boolean.TRUE;
    private T data;

    public static <T> BaseResult<T> buildRes(T my_data){
        BaseResult<T> res = new BaseResult<>();
        res.setData(my_data);
        return res;
    }
}

单测如下:

package json;

import com.alibaba.fastjson.JSON;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestContraryFastJSon
 */
public class TestContraryFastJSon {
    @Autowired
    UseFastJson useFastJson;

    @Test
    public void test_01(){
        String a = "{\"drinkId\":123,\"drinkName\":\"东鹏特饮\",\"produceDate\":\"2022-03-03 13:31:13\",\"saleDate\":\"2022-03-03 13:31:13\"}";
        Drinks drinks = JSON.parseObject(a, Drinks.class);
        System.out.println(drinks);
        //将BaseResult返回
        BaseResult<Drinks> res = BaseResult.buildRes(drinks);
        String s1 = JSON.toJSONString(res);
        System.out.println(s1);
        //此时前端需要把s1反序列化为对象
        BaseResult baseResult = JSON.parseObject(s1, BaseResult.class);
        System.out.println(baseResult);
        //问题在于这种情况下,getData拿到的是Object,不是Drinks:
        Object data = baseResult.getData();
        System.out.println(data);
    }
}

执行结果:

Drinks(drinkId=123, drinkName=东鹏特饮, produceAddress=null, produceDate=Thu Mar 03 13:31:13 CST 2022, saleDate=2022-03-03T13:31:13)
{"data":{"drinkId":123,"drinkName":"东鹏特饮","produceDate":"2022-03-03 13:31:13","saleDate":"2022-03-03 13:31:13"},"success":true}
BaseResult(isSuccess=true, data={"drinkId":123,"produceDate":"2022-03-03 13:31:13","saleDate":"2022-03-03 13:31:13","drinkName":"东鹏特饮"})
{"drinkId":123,"produceDate":"2022-03-03 13:31:13","saleDate":"2022-03-03 13:31:13","drinkName":"东鹏特饮"}

可见,问题在于反序列化后拿不到泛型类型,强制转换会失去泛型的优势,故而作如下修改:

package json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestContraryFastJSon
 */
public class TestContraryFastJSon {
    @Autowired
    UseFastJson useFastJson;

    @Test
    public void test_01(){
        String a = "{\"drinkId\":123,\"drinkName\":\"东鹏特饮\",\"produceDate\":\"2022-03-03 13:31:13\",\"saleDate\":\"2022-03-03 13:31:13\"}";
        Drinks drinks = JSON.parseObject(a, Drinks.class);
        System.out.println(drinks);
        //将BaseResult返回
        BaseResult<Drinks> res = BaseResult.buildRes(drinks);
        String s1 = JSON.toJSONString(res);
        System.out.println(s1);
        //此时前端需要把s1反序列化为对象
//        BaseResult baseResult = JSON.parseObject(s1, BaseResult.class);
//        System.out.println(baseResult);
//        //问题在于这种情况下,getData拿到的是Object,不是Drinks:
//        Object data = baseResult.getData();
//        System.out.println(data);

        //需要反序列化什么类型,就在TypeReference中传入什么类型
        BaseResult<Drinks> drinksBaseResult = JSON.parseObject(s1, new TypeReference<BaseResult<Drinks>>() {
        });
        System.out.println("反序列化后的对象:"+drinksBaseResult);
        Drinks data = drinksBaseResult.getData();
        System.out.println("data数据为:"+data);
    }
}

再次执行:

Drinks(drinkId=123, drinkName=东鹏特饮, produceAddress=null, produceDate=Thu Mar 03 13:31:13 CST 2022, saleDate=2022-03-03T13:31:13)
{"data":{"drinkId":123,"drinkName":"东鹏特饮","produceDate":"2022-03-03 13:31:13","saleDate":"2022-03-03 13:31:13"},"success":true}
反序列化后的对象:BaseResult(isSuccess=true, data=Drinks(drinkId=123, drinkName=东鹏特饮, produceAddress=null, produceDate=Thu Mar 03 13:31:13 CST 2022, saleDate=2022-03-03T13:31:13))
data数据为:Drinks(drinkId=123, drinkName=东鹏特饮, produceAddress=null, produceDate=Thu Mar 03 13:31:13 CST 2022, saleDate=2022-03-03T13:31:13)

2.3 fastJson通用配置

前言:格式缩进美化:

(1)prettyFormat:

package json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xiaoxu.boot.MainApplication;
import com.xiaoxu.json.core.UseFastJson;
import com.xiaoxu.json.vo.Drinks;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:json.TestFastJson
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class TestFastJson {
    @Autowired
    UseFastJson u;

    @Test
    public void test_01(){
        u.toJson(u.buildDrinks());
    }

    @Test
    public void test_02(){
        Drinks drinks = u.buildDrinks();
        List<Drinks> l = new ArrayList<Drinks>(){{
            for (int i = 0; i < 3; i++) {
                add(drinks);
            }
        }};
        u.toJson(l);
    }

    @Test
    public void test_03(){
        NameFilter nameFilter = (o, name, value) -> {
            //o是整个Drinks对象(u.buildDrinks()),name是成员变量名称,value是其set对应的值
            return name.toUpperCase(Locale.ROOT);
        };
        System.out.println(JSON.toJSONString(u.buildDrinks(), nameFilter, SerializerFeature.WriteMapNullValue));
    }

    @Test
    public void test_04(){
        System.out.println(JSON.toJSONString(u.buildDrinks(), true));
    }
}

执行test_04:

{
	"drinkId":123,
	"drinkName":"东鹏特饮",
	"produceDate":"2022-03-03 13:58:18",
	"saleDate":"2022-03-03 13:58:18"
}

效果上,类似python的indent参数:

json.dumps(test_dict, indent=2).encode("utf-8").decode("unicode-escape")

(2)通用配置:

package com.xiaoxu.json.vo;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.vo.Drinks
 */
@Data
public class Drinks {
    /*
    * 饮料id
    * */
    long drinkId;
    /*
    * 饮料名称
    * */
    //作用:指定属性名drinkName和json字符串的keydName是对应的关系    
    @JSONField(name = "dName")
    String drinkName;
    /*
    * 生产地址
    * */
    String produceAddress;
    /*
    * 生产日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    Date produceDate;
    /*
    * 销售日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    LocalDateTime saleDate;
}

执行test_04:
在这里插入图片描述
比如反序列化的时候,如果json字符串中没有dName这个值,同理,在转换成Drinks对象的时候,也是不能对应起来的。

还有,通用配置某个字段序列化、反序列化不参与转换的:

package com.xiaoxu.json.vo;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author xiaoxu
 * @date 2022-03-03
 * spring_boot:com.xiaoxu.json.vo.Drinks
 */
@Data
public class Drinks {
    /*
    * 饮料id
    * */
    //意思是序列化和反序列化的时候,这个字段不参与
    @JSONField(serialize = false,deserialize = false)
    long drinkId;
    /*
    * 饮料名称
    * */
    //作用:指定属性名drinkName和json字符串的keydName是对应的关系
    @JSONField(name = "dName")
    String drinkName;
    /*
    * 生产地址
    * */
    String produceAddress;
    /*
    * 生产日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    Date produceDate;
    /*
    * 销售日期
    * */
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    LocalDateTime saleDate;
}

执行test_04:

@Test
public void test_04(){
    System.out.println(JSON.toJSONString(u.buildDrinks(), true));
}

序列化结果如下:

{
	"dName":"东鹏特饮",
	"produceDate":"2022-03-03 14:08:44",
	"saleDate":"2022-03-03 14:08:44"
}

反序列化结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值