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;
@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;
@Data
public class Drinks {
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;
@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;
@Data
public class Drinks {
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;
@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;
@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;
@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) -> {
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;
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;
@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;
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<Drinks> res = BaseResult.buildRes(drinks);
String s1 = JSON.toJSONString(res);
System.out.println(s1);
BaseResult baseResult = JSON.parseObject(s1, BaseResult.class);
System.out.println(baseResult);
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;
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<Drinks> res = BaseResult.buildRes(drinks);
String s1 = JSON.toJSONString(res);
System.out.println(s1);
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;
@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) -> {
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;
@Data
public class Drinks {
long drinkId;
@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;
@Data
public class Drinks {
@JSONField(serialize = false,deserialize = false)
long drinkId;
@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"
}
反序列化结果如下:
|