fastson与jackson入门
一,简介
json: JavaScript Object Notation, JS对象简谱。
官网:JSON官网
二,使用场景
- 网络传输
描述同样的信息,json相比xml占用更少的空间,
<?xml version="1.0" encoding="uTF-8"?>
<person>
<id>1</id>
<name>张三</name>
<age>30</age>
</person>
{
"id":1,
"name":"张三",
"age": 30
}
三,java里面操作json有哪些技术?
- 所谓的操作
把java里面的bean, map, collection等转为json字符串(序列化)或反向操作(反序列化)。
- Java里操作json的技术一览
四,fastjson(漏洞频发)
<!--https://mvnrepository.com/artifact/com.alibaba/fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
4.1 序列化
- 包含null
- 日期时间格式化
- 奇怪的"$ref"
- SerializeFilter定制处理
- 对属性或属性值在序列化前做定制化处理
4.2 反序列化
- 泛型处理
- fastjson对于json中多key默认的处理就是忽略
- 美化输出
示例
package com.roadjava.json.fastjson;
import lombok.Data;
/**
* @author chengyixuan
* @see <a href="http://www.roadjava.com">乐之者Java</a>
*/
@Data
public class Person {
/**
* 用户id
*/
private Long id;
private String name;
private String pwd;
/**
* 地址
*/
private String addr;
/**
* 网站
*/
private String websiteUrl;
@JSONField(format = "yyyy-MM-dd HH:mm:ss");
private Date registerDate;
private LocalDateTime birthDay;
}
public class ResultVO<T> {
private Boolean success = Boolean.TRUE;
private T data;
private ResultVO(){}
public static <T> ResultVT<T> buildSuccess(T t) {
ResultVO<T> resultVO = new ResultVO<>();
resultVO.setData(t);
return resultVO;
}
}
public class FastJsonTest {
/**
* 测试反序列化
* json字符串 --> bean
*/
@Test
public void testDeSerialize() {
String jsonStr = "{\"addr\":\"河南\",\"birthDay\":\"2021-08-17 03:23:18\", \"id\":1}";
// 反序列化为person对象
Person person = JSON.parseObject(jsonStr, Person.class);
System.out.println(person);
//返回给调用端ResuLtVO
ResultVo<Person> personResultVo = ResultVo.buiLdSuccess(person);
String voJsonStr = JSON.toJSoNString(personResultVO);
//调用端需要把voJsonStr反序列化为对象
// ResultVO0 resultVO = JSoN.parseObject(voJsonStr, ResultVo.class);
// System.out.println("resultvo"+resultvo);
// Object data = resultVO.getData();
// 需要反序列化为什么类型,就给TypeReference传入什么类型就可以
ResultVO<Person> deSerializedVo = JSON.parseObject(voJsonStr, new TypeReference<ResultVO<Person>>) {
}
System.out.println("deSerializedVo:"+deSerializedVo);
Person data = deSerializedVo.getData();
System.out.println("data:"+data);
}
/**
* SerializeFilter定制处理.要求
* 输出的json字符串的Key是大写的。
*/
@Test
public void testSerializeFilter() {
Person person = new Person();
person.setId(1L);
// person.setName("乐之者java");
person.setPwd("123");
person.setAddr("河南");
person.setWebsiteUrl("http://www.roadjava.com");
person.setRegisterDate(new Date());
person.setBirthDay(LocalDateTime.now());
/*
* object:person对象
* name:属性
* vaLue:name属性对应的值
*/
NameFilter nameFilter = (object,name,value) -> name.toUpperCase();
String string = JsoN.toJsoNString(person,nameFilter);
System.out.println(string);
}
/**
* 测试fastjson的引用探测
* $ref: 象中多次引用了同一个其他对象的时候,序列化就会出现$ref
*/
@Test
public void test$Ref() {
List<Person>listt = new ArrayList<>();
Personpersonn= new Person();
person.setId(33L);
person.setName("乐之者java");|
list.add(person);
list.add(person);
list.add(person);
// DisableCircularReferenceDetect 禁用引用探测功能
String string = JSON.toJSONString(list, SerializerFeature.DisableCircuLarReferenceDetect);
System.out.println(string);
}
/**
* 测试序列化
* 把bean转为json字符串
*/
@Test
public void test1(){
Person person = new Person();
person.setId(1L);
person.setPwd("123");
person.setAddr("河南");
person.setWebsiteUrl("http://www.roadjava.com");
person.setRegisterDate(new Date());
person.setBirthDay(LocalDateTime.now());
// 序列化
/*
* WriteMapNullValue:指定序列化时包含null
*/
String string = JSON.toJSONString(person, SerializerFeature.WriteMapNullValue);
// 美化格式输出
// String string = JSON.toJSONString(person, true);
System.out.println(string);
}
}
4.3 通用配置
- 指定属性名和json字符串key的对应关系
- 忽略指定属性
五,jackson
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!--对Loca1DateTime等jdk8时间目期api的转化支持-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
5.1 序列化
- 只包含非null属性
- 全局配置
- 单个的bean配置
- 日期时间格式化
- 全局配置
- 单个的bean配置
5.2 反序列化
- 忽略不存在的key
- 泛型处理
示例
public class User {
/**
* 用户id
*/
private Long id;
private String name;
@Jsonignore
private String pwd;
/**
* 地址
*/
@JsonProperty("address")
private String addr;
/**
* 网站
*/
private String websiteUrl;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
private Date registerDate;
private LocalDateTime birthDay;
}
public class JacksonTest {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static ObjectMapper objectMapper = new ObjectMapper();
static {
/**
* 序列化的配置
*/
// 特殊配置: 配置序列化时只包含非空属性
// 对Data进行配置, SimpleDateFormat是线程不安全的
objectMapper.setDateFormat(new SimpLeDateFormat(DATE_TIME_FORMAT));
// 美化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 驼峰转下划线 userName -- user_name
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
/**
* 反序列的配置
*/
// 两种写法是一样的
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PEOPERTIES);
/**
* 全局的配置
*/
// 自动通过spi发现jackson的module并注册生效
// objectMapper.findAndRegisterModules();
// 手动配置JavaTimeModule并注册。
JavaTimeModule javaTimeModule = new JavaTimeMOdule();
javaTimeMOdule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
objectMapper.registerModule(javaTimeModule);
}
/**
* 对象更新, 对象的合并,如果有后者的属性有值,则用后者,否则前者的值不变
*/
@Test
public void test3() throws Exception {
User originaluser = new User();
originalUser.setId(1L);
user.setName("乐之者java");
user.setWebsiteUrl("http://www.roadjava.com");
User newUser = new User();
newUser.setId(2L);
newUser.setName("乐之者java");
newUser.setWebsiteUrl("http://www.roadjava.com”);
User updateUser = objectMapper.updateValue(originalUser, newUser);
// id:2 name: 乐之者 java websiteUrl:
System.out.println(updatedUser);
}
/**
*泛型的处理
*/
@Test
public void test3() throws Exception {
User user = new User();
user.setName("乐之者java");
user.setWebsiteUrl("http:www.roadjava.com");
ResultDTO<User> userResultDTO = ResultDTo.buiLdSuccess(user);
String dtoSerializationResult = objectMapper.writeValueAsString(userResultDTO);
// 反序列化为ResultDTO<User>
ResultDTO<User> deSerializationResult = objectMapper.readValue(dtoSerializationResult, new TypeReference<Object>() {
});
System.out.println("data:", ResultDTD.getData());
}
/**
*反序列化
*/
@Test
public void test2() throws Exception {
String str = "{\"id\":1, \"age\":88, \"pwd\":\"123\", \"addr\":\"河南\", \"websiteUr1\":}"
User user = objectMapper.readValue(str, User.class);
System.out.println(user);
}
/**
* 序列化
*/
@Test
public void testl() {
User user = new User();
user.setId(1L);
// user.setName ("乐之者java");
user.setPwd("123");
user.setAddr("河南");
user.setWebsiteUrl("http://www.roadjava.com");
user.setRegisterDate(new Date());
user.setBirthDay(LocalDateTime.now());
String string = ObjectMapper.writeValueAsString(user);
System.out.println(string);
}
}
5.3 通用配置
- 序列化: 驼峰转下划线/反序列化: 下划线转驼峰
- 指定属性名和json字符串key的对应关系
- 忽略指定属性
5.4 其他应用
- 对象更新