Jackson详解

Jackson详解Jackson 库的核心功能是将 Java 对象转换为 json 字符串 序列化 以及将 json 字符串转换为 Java 对象 反序列化 SpringMVC 默认 json 解析器便是 Jackson 与其他 Jav

大家好,欢迎来到IT知识分享网。

一、Jackson介绍

  • Jackson库的核心功能是将Java对象转换为json字符串(序列化)以及将json字符串转换为Java对象(反序列化)
  • SpringMVC默认json解析器便是Jackson

与其他Java的json的框架相比

  • Jackson 解析的json文件速度比较快
  • Jackson 运行时占用内存比较,性能比较好
  • Jackson 有灵活的API,可以很容易进行扩展和定制

核心模块由三部分组成

  • jackson-core,核心包,提供基于”流模式”解析的相关API(JsonPaser和JsonGenerator),生成和解析json
  • jackson-annotations,注解包,提供标准注解功能
  • jackson-databind ,数据绑定包,提供基于”对象绑定”解析的相关API(ObjectMapper)和”树模型”解析的相关API(JsonNode)

其中 jackson-databind内部依赖了jackson-annotations与ackson-core,故只导入jackson-databind即可

<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.0</version> </dependency> 

二、基础序列化和反序列化

  • ObjectMapper是Jackson序列化和反序列化的核心类,提供了许多用于定制序列化和反序列化的方法和配置选项
  • 默认情况下,ObjectMapper在序列化对象时,将实体所有的字段一一序列化,无论这些字段是否有值,是否为null
  • 注意:如果实体的某个字段没有提供getter方法,则该字段不会被序列化
  • ObjectMapper主要用于对Java对象(比如 POJO、List、Set、Map等等)进行序列化与反序列化

1、快速入门

 @Test public void test1() throws JsonProcessingException { 
    ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("张三"); user.setAddress(null); // 序列化 String jsonString = objectMapper.writeValueAsString(user); System.out.println("序列化字符串:" + jsonString); // 反序列化 User userFromJson = objectMapper.readValue(jsonString, User.class); System.out.println("反序列化结果:" + userFromJson); } 

输出结果:

序列化字符串:{ 
   "age":20,"name":"张三","birthday":36,"address":null} 反序列化结果:User(age=20, name=张三, birthday=Thu Jul 18 09:41:53 CST 2024, address=null) 

2、序列化API

  • String writeValueAsString(Object value)(最常用)
    • 将任何Java对象()如 POJO、List、Set、Map等)序列化为json字符串
    • 如果对象中某个属性的值为null,则默认也会序列化为null
    • 如果value为null,返回序列化的结果也返回null
  • byte[] writeValueAsBytes(Object value)
    • 将Java对象序列化为字节数组
  • writeValue(File resultFile, Object value)
    • 将Java对象序列化并输出指定文件
  • writeValue(OutputStream out, Object value)
    • 将Java对象序列化并输出到指定字节输出流
@Test public void test2() throws IOException { 
    ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("张三"); user.setAddress(null); // 序列化byt byte[] bytes = objectMapper.writeValueAsBytes(user); System.out.println("序列化字节数组:" + new String(bytes)); // 序列化到文件 objectMapper.writeValue(new File("/Users/xuchang/Documents/json.txt"), user); } 

输出结果:

在这里插入图片描述

3、反序列化API

  • T readValue(String content, Class valueType)(最常用)
    • 从给定的json字符串反序列化为Java对象
    • valueType表示反序列化的任何Class对象(如 POJO、List、Set、Map等)
    • content为空或者为null,都会报错
  • T readValue(byte[] src, Class valueType)
    • 将json内容的字节数组反序列化为Java对象
  • T readValue(File src, Class valueType)
    • 将本地json内容的文件反序列化为Java对象
  • T readValue(InputStream src, Class valueType)
    • 将json内容的字节输入流反序列化为Java对象
  • T readValue(Reader src, Class valueType)
    • 将json内容的字符输入流反序列化为Java对象
  • T readValue(URL src, Class valueType)
    • 通过网络url地址将json内容反序列化为Java对象

4、常用配置

private static final ObjectMapper objectMapper; static { 
    // 创建ObjectMapper对象 objectMapper = new ObjectMapper(); // configure方法 配置一些需要的参数 // 转换为格式化的json 显示出来的格式美化 objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 序列化的时候序列对象的那些属性 // JsonInclude.Include.NON_DEFAULT 属性为默认值不序列化 // JsonInclude.Include.ALWAYS 所有属性 // JsonInclude.Include.NON_EMPTY 属性为 空(“”) 或者为 NULL 都不序列化 // JsonInclude.Include.NON_NULL 属性为NULL 不序列化 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); // 反序列化时,遇到未知属性会不会报错 // true - 遇到没有的属性就报错 // false - 没有的属性不会管,不会报错 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 如果是空对象的时候,不抛异常 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 忽略 transient 修饰的属性 objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true); // 去除默认时间戳格式 objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // 设置为中国北京时区 objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 序列化日期格式 Date类型格式化 objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 处理java8不同时间类型 JavaTimeModule module = new JavaTimeModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(("HH:mm:ss")))); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); // 序列换成json时,将所有的long变成string(因为js中得数字类型不能包含所有的java long值) module.addSerializer(Long.TYPE, ToStringSerializer.instance); module.addSerializer(Long.class, ToStringSerializer.instance); objectMapper.registerModule(module); } @Test public void testObjectMapper() throws JsonProcessingException { 
    User user = new User(); user.setId(L); user.setAge(20); user.setBirthday(new Date()); user.setName("张三"); user.setAddress(null); user.setLocalDateTime(LocalDateTime.now()); // 序列化 String jsonString = objectMapper.writeValueAsString(user); System.out.println("序列化字符串:" + jsonString); // 注意这里添加不存在的属性hobby,反序列化不会报错 jsonString = "{\"id\":,\"age\":20,\"name\":\"张三\",\"birthday\":\"2024-07-19 11:02:19\",\"hobby\":\"打篮球\"}"; // 反序列化 User userFromJson = objectMapper.readValue(jsonString, User.class); System.out.println("反序列化结果:" + userFromJson); } @Data public class User { 
    private Long id; private Integer age; private String name; private Date birthday; private String address; private LocalDateTime localDateTime; } 

输出结果:

序列化字符串:{ 
    "id" : "", "age" : 20, "name" : "张三", "birthday" : "2024-07-19 14:27:48", "localDateTime" : "2024-07-19 14:27:48" } 反序列化结果:User(id=, age=20, name=张三, birthday=Fri Jul 19 11:02:19 CST 2024, address=null, localDateTime=null) 

三、常用注解

1、@JsonProperty

  • 用于在Java对象的属性和json字段之间建立映射关系
    • value:用于指定json属性的名称,当Java属性和json属性名称不一致时使用
    • index:指示此属性的数字索引的属性
    • access:用于指定该属性的访问方式
      • JsonAccess.READ_ONLY(只读-序列化可见)
      • JsonAccess.WRITE_ONLY(只写-反序列化可见)
      • JsonAccess.READ_WRITE(可读可写)
@Test public void test3() throws JsonProcessingException { 
    ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setAge(18); user.setName("张三"); user.setAddress("北京"); user.setBirthday(new Date()); // 序列化为json字符串 String jsonString = objectMapper.writeValueAsString(user); System.out.println(jsonString); // 反序列化为对象 String userJson = "{\"age\":18,\"user_address\":\"北京\",\"user_birthday\":59,\"user_name\":\"张三\"}"; User userValue = objectMapper.readValue(userJson, User.class); System.out.println(userValue); } @Data public class User { 
    @JsonProperty(index = 0) private Integer age; @JsonProperty(value = "user_name", access = JsonProperty.Access.READ_ONLY, index = 3) private String name; @JsonProperty(value = "user_birthday", access = JsonProperty.Access.WRITE_ONLY, index = 2) private Date birthday; @JsonProperty(value = "user_address", access = JsonProperty.Access.READ_WRITE, index = 1) private String address; } 

输出结果:

{ 
   "age":18,"user_address":"北京","user_name":"张三"} User(age=18, name=null, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京) 
  • 序列化属性名称及value设置的名称
  • 序列化根据index属性排序,反序列化还是类自上而下的顺序
  • 只读属性可以序列化,只写属性可以反序列化(读和写是相对内存中对象来理解的)

2、@JsonAlias

  • 在反序列化的时候可以让Bean的属性接收多个json字段的名称
@Test public void test4() throws JsonProcessingException { 
    ObjectMapper objectMapper = new ObjectMapper(); // 反序列化为对象 String userJson = "{\"age\":18,\"address\":\"北京\",\"birthday\":59,\"nick_name\":\"张三\"}"; User userValue = objectMapper.readValue(userJson, User.class); System.out.println(userValue); } @Data public class User { 
    private Integer age; @JsonAlias(value = { 
   "nick_name","vip_name"}) private String name; private Date birthday; private String address; } 

输出结果:

User(age=18, name=张三, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京) 

3、@JsonIgnore

  • 序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响
  • 一般标记在属性或者方法上,返回的json数据即不包含该属性
@Test public void test5() throws JsonProcessingException { 
    ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setAge(18); user.setName("张三"); user.setAddress("北京"); user.setBirthday(new Date()); // 序列化为json字符串 String jsonString = objectMapper.writeValueAsString(user); System.out.println(jsonString); // 反序列化为对象 String userJson = "{\"age\":18,\"address\":\"北京\",\"birthday\":59,\"name\":\"张三\"}"; User userValue = objectMapper.readValue(userJson, User.class); System.out.println(userValue); } @Data public class User { 
    @JsonIgnore private Integer age; @JsonIgnore private String name; private Date birthday; private String address; } 

输出结果:

{ 
   "birthday":59,"address":"北京"} User(age=null, name=null, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京) 

4、@JsonIgnoreProperties

  • 序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响
@Data @JsonIgnoreProperties({ 
   "age", "name"}) public class User { 
    private Integer age; private String name; private Date birthday; private String address; } 

5、@JsonFormat

  • 时间格式化注解
    • pattern: 表示日期的格式,比如:yyyy-MM-dd HH:mm:ss
    • timezone: 默认是GMT,中国需要GMT+8
      • 中国时间(Asia/Shanghai) = 格林尼治时间(GMT)+ 8
      • 格林尼治时间(GMT) = 世界协调时间(UTC) + 0
@Test public void test6() throws JsonProcessingException { 
    ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setAge(18); user.setName("张三"); user.setAddress("北京"); user.setBirthday(new Date()); // 序列化为json字符串 String jsonString = objectMapper.writeValueAsString(user); System.out.println(jsonString); // 反序列化为对象 User userValue = objectMapper.readValue(jsonString, User.class); System.out.println(userValue); } @Data public class User { 
    private Integer age; private String name; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date birthday; private String address; } 

输出结果:

{ 
   "age":18,"name":"张三","birthday":"2024-07-18 22:10:36","address":"北京"} User(age=18, name=张三, birthday=Thu Jul 18 22:10:36 CST 2024, address=北京) 

6、@JsonPropertyOrder

  • 用于指定实体生成json时的属性顺序
// 自定义顺序 @JsonPropertyOrder({ 
   "name", "age", "address"}) //按字母排序 @JsonPropertyOrder(alphabetic=true) 

四、高级特性

1、处理泛型

1.1、反序列化List泛型

  • 可以使用CollectionType类型反序列化,也可以构造TypeReference反序列化
@Test public void test7() throws JsonProcessingException { 
    ObjectMapper mapper = new ObjectMapper(); CollectionType javaType = mapper.getTypeFactory().constructCollectionType(List.class, User.class); // 造数据 List<User> list = new ArrayList<>(); for (int i = 0; i < 3; i++) { 
    User user = new User(); user.setId((long) i); user.setName("张三" + i); list.add(user); } System.out.println("序列化"); String jsonInString = mapper.writeValueAsString(list); System.out.println(jsonInString); System.out.println("反序列化:使用 javaType"); List<User> userList1 = mapper.readValue(jsonInString, javaType); System.out.println(userList1); System.out.println("反序列化:使用 TypeReference"); List<User> userList2 = mapper.readValue(jsonInString, new TypeReference<List<User>>() { 
   }); System.out.println(userList2); } @Data public class User { 
    private Long id; private String name; } 

输出:

序列化 [{ 
   "id":0,"name":"张三0"},{ 
   "id":1,"name":"张三1"},{ 
   "id":2,"name":"张三2"}] 反序列化:使用 javaType [User(id=0, name=张三0), User(id=1, name=张三1), User(id=2, name=张三2)] 反序列化:使用 TypeReference [User(id=0, name=张三0), User(id=1, name=张三1), User(id=2, name=张三2)] 

1.2、反序列化Map泛型

  • 可以使用MapType类型反序列化,也可以构造TypeReference反序列化
@Test public void test8() throws IOException { 
    ObjectMapper mapper = new ObjectMapper(); //第二参数是 map 的 key 的类型,第三参数是 map 的 value 的类型 MapType javaType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, User.class); // 造数据 Map<String, User> map = new HashMap<>(); for (int i = 0; i < 3; i++) { 
    User user = new User(); user.setId((long) i); user.setName("张三" + i); map.put("key" + i, user); } System.out.println("序列化"); String jsonInString = mapper.writeValueAsString(map); System.out.println(jsonInString); System.out.println("反序列化: 使用 javaType"); Map<String, User> userMap1 = mapper.readValue(jsonInString, javaType); System.out.println(userMap1); System.out.println("反序列化: 使用 TypeReference"); Map<String, User> userMap2 = mapper.readValue(jsonInString, new TypeReference<Map<String, User>>() { 
   }); System.out.println(userMap2); } 

输出结果:

序列化 { 
   "key1":{ 
   "id":1,"name":"张三1"},"key2":{ 
   "id":2,"name":"张三2"},"key0":{ 
   "id":0,"name":"张三0"}} 反序列化: 使用 javaType { 
   key1=User(id=1, name=张三1), key2=User(id=2, name=张三2), key0=User(id=0, name=张三0)} 反序列化: 使用 TypeReference { 
   key1=User(id=1, name=张三1), key2=User(id=2, name=张三2), key0=User(id=0, name=张三0)} 

2、自定义序列化和反序列化

  • 序列化类继承抽象类JsonSerializer,需要的字段或类上使用@JsonSerialize注解
  • 反序列化类继承抽象类JsonDeserializer,需要的字段或类上使用@JsonDeserialize注解
public class LongSerializer extends JsonSerializer<Long> { 
    @Override public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 
    gen.writeString(value.toString()); } } @Data public class User { 
    @JsonSerialize(using = LongSerializer.class) private Long id; private String name; } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/139495.html

(0)
上一篇 2025-06-05 17:33
下一篇 2025-06-05 17:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信