jackson与fastjson

jackson与fastjson


一、序列化与反序列化

序列化:把java中的bean,map,collection等等转换成json字符串就称为序列化;
反序列化:把json字符串转换成bean,map,collection等就叫反序列化;

当然:不仅仅是转为json字符串叫序列化,转为字节数组等其实也叫序列化,不能狭隘的理解;

二、fastjson

1.引入fastjson依赖

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

2. fastjson的序列化测试

我们本次案例以bean为例子,将bean序列化成json,所以我们需要先建一个实体类

@Data
public class Person {
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    private Date registerDate;
    private LocalDateTime birthDay;
}

再建一个测试类,使用fastjson对person对象进行序列化

	@Test
    public void test1(){
        Person person = new Person();
            person.setId(1L);
            person.setName("java");
            person.setPwd("123");
            person.setAddr("河南");
            person.setWebstieUrl("http://www.baidu.com");
            person.setRegisterDate(new Date());
            person.setBirthDay(LocalDateTime.now());
        //调用fastjson的工具类JSON的toJSONString方法就能将任意一个对象序列化成json字符串;
        String jsonStr = JSON.toJSONString(person);
        System.out.println(jsonStr);
    }

最后我们能看到,输出的jsonStr是这样的结果:

{"addr":"河南","birthDay":"2022-08-31T16:08:48.066","id":1,"name":"java","pwd":"123","registerDate":1661933328063,"webstieUrl":"http://www.baidu.com"}

这里存在几个问题:

  1. birthDay的值是LocalDateTime类型,被记录下来后,是2022-08-31T16:08:48.066这样的结果,我并不想要这样的格式;
  2. registerDate的Date类型,被记录下来后,是一个时间戳1661933328063,我是想要日期,并不想时间戳;
  3. 上面的案例中,person每一个属性都有值,如果我不给其中一个属性设置值,那么在序列化的时候,fastjson就不会序列化这个属性,也就是在最后的jsonStr中是看不到这个属性的;
    比如:我将person.setName(“java”)注释掉,也就是不对person对象的name属性赋值,那么name就是null;然后我再对person进行序列化:
	@Test
    public void test1(){
        Person person = new Person();
            person.setId(1L);
            //person.setName("java");  <<<....................看这里
            person.setPwd("123");
            person.setAddr("河南");
            person.setWebstieUrl("http://www.baidu.com");
            person.setRegisterDate(new Date());
            person.setBirthDay(LocalDateTime.now());
        //调用fastjson的工具类JSON的toJSONString方法就能将任意一个对象序列化成json字符串;
        String jsonStr = JSON.toJSONString(person);
        System.out.println(jsonStr);
    }

得到的jsonStr就是这样了,可以看到,里面少了一个name,也就是说当你person对象的name属性为null值时,你对person对象进行序列化,为null的属性是不参与序列化的;

{"addr":"河南","birthDay":"2022-08-31T16:15:28.792","id":1,"pwd":"123","registerDate":1661933728783,"webstieUrl":"http://www.baidu.com"}

2.1 如何序列化null值?

该如何解决这个问题呢?
我们只需要在JSON.toJSONString(person, SerializerFeature.WriteMapNullValue);中加上SerializerFeature.WriteMapNullValue就可以了,SerializerFeature是一个枚举,表示序列化器特征,WriteMapNullValue就表示支持null值的序列化;

	@Test
    public void test1(){
        Person person = new Person();
            person.setId(1L);
            person.setName(null);
            person.setPwd("123");
            person.setAddr("河南");
            person.setWebstieUrl("http://www.baidu.com");
            person.setRegisterDate(new Date());
            person.setBirthDay(LocalDateTime.now());
        String jsonStr = JSON.toJSONString(person, SerializerFeature.WriteMapNullValue);
        System.out.println(jsonStr);
    }

最后我们就能看到,即便这个name是null,也被序列化出来了;
在这里插入图片描述

2.2 序列化时如何格式化时间?

给日期属性上加@JSONField注解,通过format属性指定我们想要的时间格式format = “yyyy-MM-dd HH:mm:ss” ,下次在序列化时,就能将这些时间属性序列化成我们想要的格式;

@Data
public class Person {
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接

    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date registerDate;
    
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthDay;
}
	@Test
    public void test1(){
        Person person = new Person();
            person.setId(1L);
            person.setName(null);
            person.setPwd("123");
            person.setAddr("河南");
            person.setWebstieUrl("http://www.baidu.com");
            person.setRegisterDate(new Date());
            person.setBirthDay(LocalDateTime.now());
        String jsonStr = JSON.toJSONString(person, SerializerFeature.WriteMapNullValue);
        System.out.println(jsonStr);
    }

这就是最后序列化完的结果:
在这里插入图片描述

2.3 禁用fastjson的引用探测

什么是引用探测?看下面的例子:

	@Test
    public void test2(){
        Person person = new Person();
            person.setId(1L);
            person.setName(null);
            person.setPwd("123");
        List<Person> list = new ArrayList<>();
            list.add(person);
            list.add(person);
            list.add(person);
        String jsonStr = JSON.toJSONString(list);
        System.out.println(jsonStr);
    }

我们创建出一个person对象,将这一个对象放三次放入list中,再序列化这个list;
最后的序列化结果就是这样:

[{"id":1,"pwd":"123"},{"$ref":"$[0]"},{"$ref":"$[0]"}]

这是因为fastjson在进行序列化时,当它发现里面同一个对象有多个时,它就只会序列化一次,比如这个list中的person对象都是同一个,所以它就只会序列化第一个person,后面的person就用引用来代替,不再进行序列化,所以后面的person就是显示成了" r e f " 这样的格式;这就存在问题:我们返回给前端的 j s o n 中,存在一个 " ref"这样的格式; 这就存在问题:我们返回给前端的json中,存在一个" ref"这样的格式;这就存在问题:我们返回给前端的json中,存在一个"ref"是什么鬼?所以需要解决;

解决办法:使用SerializerFeature.DisableCircularReferenceDetect禁用引用探测功能即可;

	@Test
    public void test2(){
        Person person = new Person();
            person.setId(1L);
            person.setName(null);
            person.setPwd("123");
        List<Person> list = new ArrayList<>();
            list.add(person);
            list.add(person);
            list.add(person);
        //SerializerFeature.DisableCircularReferenceDetect表示禁用引用探测功能;
        String jsonStr = JSON.toJSONString(list,SerializerFeature.DisableCircularReferenceDetect);《《《------看这里
        System.out.println(jsonStr);
    }

2.4 SerialFilter定制化处理

2.5 fastjson的美化输出

2.6 注意:

JSON.toJSONString(Object o , SerializerFeature…serializerFeature) 后面是可以跟SerializerFeature类型的可变参数的
所以你可以在JSON.toJSONString中传多个SerializerFeature,比如:

我这么写,既禁用了引用探测,又支持了null值的序列化:

String jsonStr = JSON.toJSONString(list,SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue)

3. fastjson的反序列化

3.1 fastjson如何反序列化?

我们再把person的json字符串反序列化成person对象:

	@Test
    public void test3(){
        String jsonStr = "{\"addr\":\"河南\",\"birthDay\":\"2022-08-31T17:08:17.934\",\"id\":1,\"name\":null,\"pwd\":\"123\",\"registerDate\":1661936897930,\"webstieUrl\":\"http://www.baidu.com\"}";
        Person person = JSON.parseObject(jsonStr, Person.class);
        System.out.println(person);
    }

最后得到的结果就是这样的;

Person(id=1, name=null, pwd=123, addr=河南, webstieUrl=http://www.baidu.com, registerDate=Wed Aug 31 17:08:17 CST 2022, birthDay=2022-08-31T17:08:17.934)

如果你是要把json字符串反序列化成对象就用:

JSON.parseObject(第一个参数是json字符串, 第二个参数是你要转换的目标类);

如果你要把 json字符串反序列化成集合,就用:

JSON.parseArray()

这个方法也是重载了的,你们自己去看重载方法的参数; 这个方法最后得到的是一个List

3.2 反序列化存在的问题

在fastjson中,针对泛型的反序列化存在问题:具体问题可以看下面案例的注释,我不太好用于总结出它的问题:

	@Test
    public void test3(){
        String jsonStr = "{\"addr\":\"河南\",\"birthDay\":\"2022-08-31T17:08:17.934\",\"id\":1,\"name\":null,\"pwd\":\"123\",\"registerDate\":1661936897930,\"webstieUrl\":\"http://www.baidu.com\"}";
        
        //将person的字符串反序列化成person对象
        Person person = JSON.parseObject(jsonStr, Person.class);
        //我把person对象放入AjaxResult中
        AjaxResult<Person> ajaxResult = AjaxResult.me().setSuccess(true).setData(person);
        //将ajaxResult序列化成JSON字符串
        String s = JSON.toJSONString(ajaxResult, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
        //再将json字符串反序列化成AjaxResult对象
        AjaxResult ajaxResult1 = JSON.parseObject(s, AjaxResult.class);
        //然后我们再通过AjaxResult对象getData()看能不能拿到里面的person对象:
        //结果得到了一个Object对象,并不是我们想要的Person对象,如果我们想要Person对象,还需要强转一下,这不优雅;
        Object data = ajaxResult1.getData();
    }

解决办法:
我们使用JSON.parseObject()的重载方法,传一个new TypeRefrence进去;

	@Test
    public void test3(){
        String jsonStr = "{\"addr\":\"河南\",\"birthDay\":\"2022-08-31T17:08:17.934\",\"id\":1,\"name\":null,\"pwd\":\"123\",\"registerDate\":1661936897930,\"webstieUrl\":\"http://www.baidu.com\"}";
        
        //将person的字符串反序列化成person对象
        Person person = JSON.parseObject(jsonStr, Person.class);
        //我把person对象放入AjaxResult中
        AjaxResult<Person> ajaxResult = AjaxResult.me().setSuccess(true).setData(person);
        //将ajaxResult序列化成JSON字符串
        String s = JSON.toJSONString(ajaxResult, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
        //再将json字符串反序列化成AjaxResult对象
        AjaxResult ajaxResult1 = JSON.parseObject(s,new TypeReference<AjaxResult<Person>>(){});
        //然后我们再通过AjaxResult对象getData()看能不能拿到里面的person对象:
        //结果得到了一个Object对象,并不是我们想要的Person对象,如果我们想要Person对象,还需要强转一下,这不优雅;
        Object data = ajaxResult1.getData();
    }

注意:new TypeReference里面的泛型,并且最后要加一对大括号:我也不知道为什么;
注意:加了new TypeReference,并且指定了里面的泛型后,parseObject的入参里就不用指定目标类的class对象了,因为new TypeReference里面已经包含了;
这样操作后,我们得到ajaxResult1,再来.getData()就能得到正确的Person类型了,而不是Object类型;
在这里插入图片描述

4. fastjson的通用配置

4.1 更换json格式中的key

@Data
public class Person {
    private Long id;
    private String name;
    
    @JSONField(name = "password")	<<<..............看这里
    private String pwd;
    
    @JSONField(name = "address")	<<<..............看这里
    private String addr;
    private String webstieUrl; //个人网站连接
    
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date registerDate;

    @JSONField(format = "yyyy-MM-dd")
    private LocalDateTime birthDay;
}

通过@JSONField注解,用name方法指定指定一个值,比如在属性private String pwd上,指定了一个name = “password”,那么在序列化成json格式的时候,pwd这一个属性,就会被序列化成 “address”:密码值 这样的格式;addr就被替换成了address;

然后反过来,当有下面这样一个json字符串,我们要把它反序列化成perrson对象时:

"{\"addr\":\"河南\",\"birthDay\":\"2022-08-31\",\"id\":1,\"name\":null,\"pwd\":\"123\",\"registerDate\":\"2022-08-31 21:18:52\",\"webstieUrl\":\"http://www.baidu.com\"}"

由于你Person类的add属性上被加上了 @JSONField(name = “password”),那么在反序列化的时候,private String pwd这一个属性是不会被赋上值的;

@Data
public class Person {
    private Long id;
    private String name;
    
    @JSONField(name = "password")	<<<..............看这里
    private String pwd;
    
    @JSONField(name = "address")	<<<..............看这里
    private String addr;
    private String webstieUrl; //个人网站连接
    
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date registerDate;

    @JSONField(format = "yyyy-MM-dd")
    private LocalDateTime birthDay;
}

只有你这个json字符串里面的addr,变成address的时候,才能被反序列化成person对象,就是下图圈起来这个位置被改成address:
在这里插入图片描述

4.2 忽略指定属性

使用@JSONField注解,serizlize方法为true表示该属性参与序列化,false表示不参与序列化;
deserialize是反序列化的意思,deserialize方法为true表示该属性参与反序列化,false表示不参与反序列化;

这个功能的用处:就是有时候我们不想把某一个类的其中一个或者几个属性返回给前端,我就可以将其设置为不参与序列化;

用法如下:
在这里插入图片描述

三、jackson

1. jackson依赖

<dependency>
	  <groupId>com.fasterxml.jackson.core</groupId>
	  <artifactId>jackson-databind</artifactId>
	  <version>2.10.1</version>
</dependency>
<!--对LocalDateTime等jdk8时间日期api的转换支持-->
<dependency>
	  <groupId>com.fasterxml.jackson.datatype</groupId>
	  <artifactId>jackson-datatype-jsr310</artifactId>
	  <version>2.10.1</version>
</dependency>

2.jackson的序列化

为了跟fastjson做区分,我们新建一个User类,用来做序列化

@Data
public class User{
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    private Date registerDate;
    private LocalDateTime birthDay;
}
public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
	static{
	}

	@Test
    public  void test1() throws JsonProcessingException{
        User user= new User ();
            user.setId(1L);
            user.setName(null);
            user.setPwd("123");
            user.setAddr("河南");
            user.setWebstieUrl("http://www.baidu.com");
            user.setRegisterDate(new Date());
            user.setBirthDay(LocalDateTime.now());
        String jsonStr = objectMapper.writeAsValueString(user);
        System.out.println(jsonStr);
    }
}    

最后序列化的结果:我们可以看到,日期格式依然不是我们想要的,registerDate依然是时间戳,birthDay则变成了另一种日期格式,很长一串,显然都不是我们想要的;在这里插入图片描述在这里插入图片描述

2.1 jackson序列化时null值的处理

跟fastjson不同的是,fastjson是默认不会序列化null值的,也就是说一个属性为null值时,在序列化后,是看不到这个属性的;
但是jackson就刚好跟它相反,它默认就是会序列化null值的;

2.2 jackson的配置

2.2.1 全局配置:

注意:jackson中的ObjectMapper是可以进行配置的,通常都是将ObjectMapper对象定义成一个静态属性,并且在下面写一个静态代码块,在静态代码块中对ObjectMapper对象进行配置;
为什么要将ObjectMapper对象定义成一个静态属性?又为什么要在静态代码块中对ObjectMapper对象进行配置呢?

因为加了static的对象会被优先加载,静态代码块中的代码也会被优先加载,当你运行这个类的时候,ObjectMapper对象就已经是被配置好了的,所以才设置成静态属性和静态代码块:

注意:通过静态属性+静态代码块的方式,这是属于全局配置;

下面就是属于全局配置:

public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
	static{
		//配置序列化时,不序列化null值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
	}

	@Test
    public  void test1() throws JsonProcessingException{
        User user= new User ();
            user.setId(1L);
            user.setName(null);
            user.setPwd("123");
            user.setAddr("河南");
            user.setWebstieUrl("http://www.baidu.com");
            user.setRegisterDate(new Date());
            user.setBirthDay(LocalDateTime.now());
        String jsonStr = objectMapper.writeAsValueString(user);  //writeAsValueString是需要抛异常的
        System.out.println(jsonStr);
    }
}    
2.2.2 对单个bean进行配置:

如果你要对单个bean进行配置,就要找到这个bean,在类上加@JsonInclude(JsonInclude.Include.NON_NULL)就可以了,就表示对于该类的序列化,不会序列化null值;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User{
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    private Date registerDate;
    private LocalDateTime birthDay;
}

2.3 jackson中对日期时间的处理

通过 @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”,timezone =“GMT+8”)对日期时间属性进行处理

@Data
public class User{
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private Date registerDate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private LocalDateTime birthDay;
}

加上这个注解后,我们再次对其进行序列化:

public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
	static{
	}

	@Test
    public  void test1() throws JsonProcessingException{
        User user= new User ();
            user.setId(1L);
            user.setName(null);
            user.setPwd("123");
            user.setAddr("河南");
            user.setWebstieUrl("http://www.baidu.com");
            user.setRegisterDate(new Date());
            user.setBirthDay(LocalDateTime.now());
        String jsonStr = objectMapper.writeAsValueString(user);
        System.out.println(jsonStr);
    }
}    

我们发现还是Date类型的registerDate成功序列化成我们想要的格式了,但是LocalDateTime类型的birthDay还是老样子,这是为什么呢?
在这里插入图片描述
解决办法:两个条件;
条件一:你必须添加这个依赖

<!--对LocalDateTime等jdk8时间日期api的转换支持-->
<dependency>
	  <groupId>com.fasterxml.jackson.datatype</groupId>
	  <artifactId>jackson-datatype-jsr310</artifactId>
	  <version>2.10.1</version>
</dependency>

条件二:必须在静态代码块中,加上objectMapper.findAndRegisterModules()表示自动通过spi发现jackson的moudle并注册,否则是不能完成对LocalDateTime类型属性的序列化的;

public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
	static{
		//配置自动通过spi发现jackson的moudle并注册
        objectMapper.findAndRegisterModules(); <<<<<----------看这里
	}

	@Test
    public  void test1() throws JsonProcessingException{
        User user= new User ();
            user.setId(1L);
            user.setName(null);
            user.setPwd("123");
            user.setAddr("河南");
            user.setWebstieUrl("http://www.baidu.com");
            user.setRegisterDate(new Date());
            user.setBirthDay(LocalDateTime.now());
        String jsonStr = objectMapper.writeAsValueString(user);
        System.out.println(jsonStr);
    }
}    

以上弄好后,我们再进行序列化,就发现LocalDateTime类型的birthDay就序列化好了:

2.4 美化输出

User类如下:

@Data
public class User {
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private Date registerDate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private LocalDateTime birthDay;
}
public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
	static{
		//配置自动通过spi发现jackson的moudle并注册
        objectMapper.findAndRegisterModules(); 
        //配置序列化的美化输出,true表示开启美化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);	<<<<<----------看这里
	}

	@Test
    public  void test1() throws JsonProcessingException{
        User user= new User ();
            user.setId(1L);
            user.setName(null);
            user.setPwd("123");
            user.setAddr("河南");
            user.setWebstieUrl("http://www.baidu.com");
            user.setRegisterDate(new Date());
            user.setBirthDay(LocalDateTime.now());
        String jsonStr = objectMapper.writeAsValueString(user);
        System.out.println(jsonStr);
    }
}    

结果如下:

{
  "id" : 1,
  "pwd" : "123",
  "addr" : "河南",
  "webstieUrl" : "http://www.baidu.com",
  "registerDate" : "2022-08-31 23:28:04",
  "birthDay" : "2022-08-31 23:28:04"
}

3.jackson的反序列化

jackson中反序列化是通过objectMapper调用readValue方法实现的:

	@Test
    public void test6() throws JsonProcessingException {
        String jsonStr = "{\"id\":1,\"pwd\":\"123\",\"addr\":\"河南\",\"webstieUrl\":\"http://www.baidu.com\",\"registerDate\":\"2022-08-31 23:19:00\",\"birthDay\":\"2022-08-31 23:19:00\"}";
        User user = objectMapper.readValue(jsonStr, User.class);
        System.out.println(user);
    }

结果:

User(id=1, name=null, pwd=123, addr=河南, webstieUrl=http://www.baidu.com, registerDate=Wed Aug 31 23:19:00 CST 2022, birthDay=2022-08-31T23:19)

注意:objectMapper.readValue(jsonStr, User.class)中,User.class是要反序列成的目标类

3.1 忽略json字符串中不存在的key

在fastjson中是默认忽略不存在的key的,但是在jackson默认是不忽略的,需要我们进行配置:

比如,这个json字符串中,我给它加了一个User类没有的属性age, 这个age就是这个json字符串中不存在的key(意思就是在User类中不存在这个属性)
在这里插入图片描述
此时我们再把它反序列化为User对象时,就会报错,提示不认识的属性:age
在这里插入图片描述
那该怎么解决呢?

static{
		//配置自动通过spi发现jackson的moudle并注册
        objectMapper.findAndRegisterModules(); 
        //配置序列化的美化输出,true表示开启美化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
        //表示:在反序列化时,针对哪些目标对象中没有的属性jackson会直接忽略掉,就能反序列化成功
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);	<<<<-------看这里	
} 	

注意:objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false)也成下面这样也是可以的,两种不同的写法,都表示同样的意思:

objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

3.2 泛型的处理

jackson中fastjson中的泛型处理基本都是一样的,在反序列化时都要new TypeReference,它们俩取的名字都叫TypeReference,我们在用的时候,一定区分开,一个是fastjson的,一个是jackson的;

	@Test
    public void test7() throws Exception {
        User user = new User();
            user.setName("许海");
            user.setAddr("南岸区");
        //将user装进AjaxResult<User>中
        AjaxResult<User> ajaxResult = AjaxResult.me().setSuccess(true).setData(user);
        //将ajaxResult进行序列化
        String jsonStr = objectMapper.writeValueAsString(ajaxResult);
        //再反序列化
        AjaxResult<User> userAjaxResult = objectMapper.readValue(jsonStr, new com.fasterxml.jackson.core.type.TypeReference<AjaxResult<User>>() {
        });
        User data = userAjaxResult.getData();
    }

4. jackson通用配置

什么叫通用配置?
通用配置就是,只要你配置了,序列化和反序列化时都会起作用 ;

4.1 将驼峰转下划线

将属性驼峰转下划线,比如将属性userName在序列化时,转换为user_name;
这个配置就表示将驼峰转下划线,

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
@Data
public class User {
    private Long id;
    private String name;
    private String pwd;
    private String addr;
    private String webstieUrl; //个人网站连接
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private Date registerDate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private LocalDateTime birthDay;
}
@SpringBootTest
public class myTest{
	private static ObjectMapper objectMapper = new ObjectMapper();
    static{
        //配置序列化时,不序列化null值
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //配置自动通过spi发现jackson的moudle并注册
        objectMapper.findAndRegisterModules();
        //表示配置序列化的美化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
        //表示:在反序列化时,针对哪些目标对象中没有的属性不报错,也能反序列化成功
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        //序列化时驼峰转下划线,反序列化时下划线转驼峰
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    }

    @Test
    public void test5() throws JsonProcessingException {
        User user= new User();
        user.setId(1L);
        user.setName(null);
        user.setPwd("123");
        user.setAddr("河南");
        user.setWebstieUrl("http://www.baidu.com");
        user.setRegisterDate(new Date());
        user.setBirthDay(LocalDateTime.now());
        //序列化
        String jsonStr = objectMapper.writeValueAsString(user);
        System.out.println(jsonStr);
		//反序列化
        System.out.println(objectMapper.readValue(jsonStr, User.class));
    }
}

这是序列化的结果:我们可以看到birthDay等驼峰命名的属性,在序列化时已经被转成了下划线:

{
  "id" : 1,
  "name" : null,
  "pwd" : "123",
  "addr" : "河南",
  "webstie_url" : "http://www.baidu.com",
  "register_date" : "2022-09-01 08:57:10",
  "birth_day" : "2022-09-01 08:57:10"
}

再看反序列化的结果:jsonStr中的下划线已经被转换为驼峰了;

User(id=1, name=null, pwd=123, addr=河南, webstieUrl=http://www.baidu.com, registerDate=Thu Sep 01 08:57:10 CST 2022, birthDay=2022-09-01T08:57:10)

4.2 指定属性名与json字符串中key的对应关系

@JsonProperty(“address”):

@Data
public class User {
    private Long id;
    private String name;
    private String pwd;
    @JsonProperty("address")  <<<-----看这里
    private String addr;
    private String webstieUrl; //个人网站连接
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private Date registerDate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private LocalDateTime birthDay;

通过@JsonProperty(“address”)这个注解,就能指定属性addr被序列化后key变成address

4.3 忽略某属性的序列化

@JsonIgnore:

@Data
public class User {
    private Long id;
    private String name;
    @JsonIgnore
    private String pwd;
    @JsonProperty("address")  <<<-----看这里
    private String addr;
    private String webstieUrl; //个人网站连接
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private Date registerDate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone ="GMT+8")
    private LocalDateTime birthDay;

头上加了@JsonIgnore的属性就不会参与序列化了,
也不会参与反序列化:就是说json字符串中有pwd这个key,“pwd”:“115409” ,也有值115409,但是就无法把115409赋值给pwd这个属性,这就是无法参与反序列化;

5. 利用jackson来进行对象的更新

这个操作也可以叫对象的合并, 如果后者的属性有值,则用后者的值 ,否则用前者的值;

User user1 = new User();
   user1.setId(1L);
    user1.setAddr("重庆");
User user2 = new User();
    user2.setId(2L);
    user2.setAddr("成都");
User user = objectMapper.updateValue(user1, user2);

结果:

User(id=2, name=null, pwd=null, addr=成都, webstieUrl=null, registerDate=null, birthDay=null)

总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值