01 jackson介绍

1 简单介绍

Jackson 是用来序列化和反序列化 json 的 Java 的开源框架。Spring MVC 的默认 json 解析器便是 Jackson。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。

Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson
ackson 的核心模块由三部分组成。

  • jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

  • jackson-annotations,注解包,提供标准注解功能;

  • jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。

若想在 Java 代码中使用 Jackson 的核心模块的 jar 包 ,需要在 pom.xml 中添加如下信息。

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

说明
jackson-databind 依赖 jackson-core 和 jackson-annotations,当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中。在添加相关依赖包之后,就可以使用 Jackson。

2 快速入门

2.0 准备工作

  • 新建一个maven工程json-study
  • 导入依赖
<dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.10</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13-beta-3</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.22</version>
        </dependency>
    </dependencies>
  • 准备一个model
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String name;
    private Integer age;
    private Date date;
    private int height;
    private List<String> course;
    // 班主任,
    private Teacher teacher;
}
@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String name;
}

2.1 序列化

简单使用

/**
 * 测试序列化
 * @throws JsonProcessingException
 */
@Test
public void test01() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    Student student = build();
    String json = objectMapper.writeValueAsString(student);
    System.out.println(json);
}
private Student build() {
   return Student.builder()
           .age(18)
           .date(new Date())
           .height(100)
           .course(Arrays.asList("Math","English","Chinese"))
           .teacher(Teacher.builder().name("张老师").build())
           .name("Jackson").build();
}

输出

{"name":"Jackson","age":18,"date":1603263016919,"height":100,"course":["Math","English","Chinese"],"teacher":{"name":"张老师"}}

格式化json

@Test
public void test02() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    Student student = build();
    String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(json);
}

输出

{
  "name" : "Jackson",
  "age" : 18,
  "date" : 1603263150974,
  "height" : 100,
  "course" : [ "Math", "English", "Chinese" ],
  "teacher" : {
    "name" : "张老师"
  }
}

2.2 反序列化

/***
* 测试反序列化
* @return
*/
@Test
public void test03() throws IOException {
   ObjectMapper objectMapper = new ObjectMapper();
   Student student = build();
   // 先序列化
   String json = objectMapper.writeValueAsString(student);
   //String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
   // 反序列化
   Student studentFromJson = objectMapper.readValue(json, Student.class);
   System.out.println(studentFromJson);
}

2.3 总结

ObjectMapper 通过 writeValue 系列方法将 java 对象序列化为 json,并将 json 存储成不同的格式,·String·,ByteArrayWriterFileOutStreamDataOutput

ObjectMapper 通过readValue系列方法从不同的数据源像 StringByte ArrayReaderFileURLInputStream将 json 反序列化为 java 对象。

3 ObjectMapper配置

在调用 writeValue 或调用 readValue 方法之前,往往需要设置 ObjectMapper 的相关配置信息。这些配置信息应用 java 对象的所有属性上。示例如下:

//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//在序列化时自定义时间日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//在序列化时忽略值为 null 的属性
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//在序列化时忽略值为默认值的属性
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);

更多配置信息可以查看 Jackson 的 DeserializationFeature,SerializationFeature 和 Include。

3.1 演示

测试刚刚上面的几个配置

DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

  • 不忽略,默认也是不忽略
	public ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void test01() throws IOException {
        // 在反序列化时不忽略在 json 中存在但 Java 对象不存在的属性
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,true);
        //Teacher 中没有age属性
        String json = "{\n" +
                "  \"name\": \"张老师\",\n" +
                "  \"age\": 40\n" +
                "}";
        Teacher teacher = objectMapper.readValue(json, Teacher.class);
        System.out.println(teacher);
    }

默认就是true,不会忽略在 json 中存在但 Java 对象不存在的属性,这时候在反序列化的时候就会报错

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "age" (class study.wyy.json.study.jackson.model.Teacher), not marked as ignorable (one known property: "name"])
 at [Source: (String)"{
  "name": "张老师",
  "age": 40
}"; line: 3, column: 12] (through reference chain: study.wyy.json.study.jackson.model.Teacher["age"])

	at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:823)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1153)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
	at study.wyy.json.study.jackson.demo.ConfigObjectMapper.test01(ConfigObjectMapper.java:29)
  • 设置为忽略
@Test
public void test02() throws IOException {
    // 在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
    //language=JSON
    String json = "{\n" +
            "  \"name\": \"张老师\",\n" +
            "  \"age\": 40\n" +
            "}";
    Teacher teacher = objectMapper.readValue(json, Teacher.class);
    System.out.println(teacher);
}
Teacher(name=张老师)

SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
在序列化时日期是否以时间戳的形式,默认是true,可参考快速入门例子

@Test
public void test03() throws IOException {
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    Student student = build();
    String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(value);
}
{
  "name" : "Jackson",
  "age" : 18,
  "date" : "2020-10-21T08:11:01.584+0000",
  "height" : 100,
  "course" : [ "Math", "English", "Chinese" ],
  "teacher" : {
    "name" : "张老师"
  }
}

在序列化时自定义时间日期格式
在序列化时日期是否以时间戳的形式为false时候,默认是2020-10-21T08:11:01.584+0000

如何自定义呢

/**
 * 自定义时间序列化格式
 * @throws IOException
 */
@Test
public void test04() throws IOException {
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
    Student student = build();
    String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(value);
}
{
  "name" : "Jackson",
  "age" : 18,
  "date" : "2020/10/21 16:26:14",
  "height" : 100,
  "course" : [ "Math", "English", "Chinese" ],
  "teacher" : {
    "name" : "张老师"
  }
}

在序列化时忽略值为 null 的属性

@Test
public void test05() throws IOException {
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    Student student = build();
    student.setAge(null);
    String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(value);
}
{
  "name" : "Jackson",
  "date" : 1603269862759,
  "height" : 100,
  "course" : [ "Math", "English", "Chinese" ],
  "teacher" : {
    "name" : "张老师"
  }
}

在序列化时忽略值为默认值的属性

  • 先不忽略
 @Test
public void test06() throws IOException {
    //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
    Student student = Student.builder()
            .name("jackson")
            .date(new Date())
            .age(18)
            .build();
    String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(value);
}
{
  "name" : "jackson",
  "age" : 18,
  "date" : 1603270077300,
  "height" : 0,
  "course" : null,
  "teacher" : null
}
  • 设置忽略
@Test
public void test06() throws IOException {
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
    Student student = Student.builder()
            .name("jackson")
            .date(new Date())
            .age(18)
            .build();
    String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(value);
}
{
  "name" : "jackson",
  "age" : 18,
  "date" : 1603270133718
}

那些没有设置的属性,这里就没有序列化。

3.2 补充一些其他配置

// 美化输出
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 允许序列化空的POJO类
// (否则会抛出异常)
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 把java.util.Date, Calendar输出为数字(时间戳)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

// 在遇到未知属性的时候不抛出异常
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 强制JSON 空字符串("")转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

// 在JSON中允许C/C++ 样式的注释(非标准,默认禁用)
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许没有引号的字段名(非标准)
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号(非标准)
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 强制转义非ASCII字符
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
// 将内容包裹为一个JSON属性,属性名由@JsonRootName注解指定
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

4 用注解管理映射

准备一个模型

@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class StudentWithAnnotations {

    private String name;
    private Integer age;
    private Date date;
    private int height;
    @JsonIgnore
    private List<String> course;
    // 班主任,
    private Teacher teacher;
}

4.1 JsonIgnore

可用于字段、getter/setter、构造函数参数上,作用相同,都会对相应的字段产生影响。使相应字段不参与序列化和反序列化。

  • course设置了@JsonIgnore注解,序列化的时候会忽略这个字段
public ObjectMapper objectMapper = new ObjectMapper();

/**
 * 测试忽略, 
 * @throws IOException
 */
@Test
public void testJsonIgnore() throws IOException {

    StudentWithAnnotations student = buildStudentWithAnnotations();
    String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(json);
}
    public StudentWithAnnotations buildStudentWithAnnotations() {
        return StudentWithAnnotations.builder()
                .age(18)
                .date(new Date())
                .height(100)
                .course(Arrays.asList("Math","English","Chinese"))
                .teacher(Teacher.builder().name("张老师").build())
                .name("Jackson").build();
    }

输出

{
  "name" : "Jackson",
  "age" : 18,
  "date" : 1603271223291,
  "height" : 100,
  "teacher" : {
    "name" : "张老师"
  }
}

那发序列化的时候呢

/***
  * 测试反序列化
  * @return
  */
 @Test
 public void testJsonIgnore2() throws IOException {
     ObjectMapper objectMapper = new ObjectMapper();
     Student student = build();
     // 先序列化
     String json = objectMapper.writeValueAsString(student);
     System.out.println();
     // 反序列化
     StudentWithAnnotations studentFromJson = objectMapper.readValue(json, StudentWithAnnotations.class);
     System.out.println(studentFromJson);
 }

输出:course也是null,也会忽略

StudentWithAnnotations(name=Jackson, age=18, date=Wed Oct 21 17:10:18 CST 2020, height=100, course=null, teacher=Teacher(name=张老师))

4.2 @JsonProperty

用于属性,把属性的名称序列化时转换为另外一个名称。

@JsonProperty("firstName")
private String name;
@Test
public void testJsonProperty() throws IOException {
    StudentWithAnnotations student = buildStudentWithAnnotations();

    String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(json);
}

输出: name属性在序列化json的时候,变成了firstName

{
  "age" : 18,
  "date" : 1603272038044,
  "height" : 100,
  "teacher" : {
    "name" : "张老师"
  },
  "firstName" : "Jackson"
}

反序列化

/***
* 测试反序列化
* @return
*/
@Test
public void testJsonProperty2() throws IOException {
   StudentWithAnnotations student = buildStudentWithAnnotations();

   String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
   // 反序列化
   StudentWithAnnotations studentFromJson = objectMapper.readValue(json, StudentWithAnnotations.class);
   System.out.println(studentFromJson);
}

输出:同一json字符串中的firstName也是可以映射到name属性的

StudentWithAnnotations(name=Jackson, age=18, date=Wed Oct 21 17:22:55 CST 2020, height=100, course=null, teacher=Teacher(name=张老师))

4.3 JsonFormat

用于属性或者方法,把属性的格式序列化时转换成指定的格式。

@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm")
private Date date;
@Test
public void testJsonFormat() throws IOException {
    StudentWithAnnotations student = buildStudentWithAnnotations();
    String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(student);
    System.out.println(json);
}

输出

{
  "age" : 18,
  "date" : "2020-10-21 17:33",
  "height" : 100,
  "teacher" : {
    "name" : "张老师"
  },
  "firstName" : "Jackson"
}

4.4 注解总结

注解用法
@JsonProperty用于属性,把属性的名称序列化时转换为另外一个名称。示例:@JsonProperty(“birth_date”) private Date birthDate
@JsonIgnore可用于字段、getter/setter、构造函数参数上,作用相同,都会对相应的字段产生影响。使相应字段不参与序列化和反序列化。
@JsonIgnoreProperties该注解是类注解。该注解在Java类和JSON不完全匹配的时候使用。
@JsonFormat用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例:@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) public Date getBirthDate()
@JsonPropertyOrder用于类, 和 @JsonProperty 的index属性类似,指定属性在序列化时 json 中的顺序 , 示例:@JsonPropertyOrder({ “birth_Date”, “name” }) public class Person
@JsonCreator用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。示例:@JsonCreator public Person(@JsonProperty(“name”)String name) {…}
@JsonAnySetter用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); }
@JsonAnyGetter用于方法 ,获取所有未序列化的属性 public Map<String, Object> any() { return map; }
@JsonNaming类注解。序列化的时候该注解可将驼峰命名的字段名转换为下划线分隔的小写字母命名方式。反序列化的时候可以将下划线分隔的小写字母转换为驼峰命名的字段名。示例:@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@JsonRootName类注解。需开启mapper.enable(SerializationFeature.WRAP_ROOT_VALUE),用于序列化时输出带有根属性名称的 JSON 串,形式如 {“root_name”:{“id”:1,“name”:“zhangsan”}}。但不支持该 JSON 串反序列化。

5 日期处理

不同类型的日期类型,JackSon 的处理方式也不同。

5.1 普通日期

对于日期类型为java.util.Calendar, java.util.GregorianCalendar,java.sql.Date, java.util.Date, java.sql.Timestamp,若不指定格式,在 json 文件中将序列化为 long 类型的数据。显然这种默认格式,可读性差,转换格式是必要的。

JackSon 有很多方式转换日期格式。

  • 注解方式,使用 @JsonFormat 注解指定日期格式。

  • ObjectMapper 方式,调用 ObjectMapper 的方法 setDateFormat,将序列化为指定格式的 string 类型的数据。

上面已经介绍过啦

5.2 java8的日期

对于日期类型为java.time.LocalDate, java.time.LocalDateTime,还需要添加代码 ,同时添加相应的依赖 jar 包。

ObjectMapper mapper = new ObjectMapper()
                .registerModule(new JavaTimeModule())

演示

给Teacher增加两个属性

@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String name;
    private LocalDate localDate;
    private LocalDateTime localDateTime;
}
@Test
   public void test01() throws JsonProcessingException {
       Teacher teacher = new Teacher();
       teacher.setName("张老师");
       teacher.setLocalDate(LocalDate.now());
       teacher.setLocalDateTime(LocalDateTime.now());
       objectMapper.registerModule(new JavaTimeModule());
       String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(teacher);
       System.out.println(value);
   }

输出:

{
  "name" : "张老师",
  "localDate" : [ 2020, 10, 21 ],
  "localDateTime" : [ 2020, 10, 21, 17, 55, 53, 375000000 ]
}

这个时间格式不太友好,可以直接使用我们的注解去进行格式化

@Data
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String name;

    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
    private LocalDate localDate;
    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;
}

再次运行结果

{
  "name" : "张老师",
  "localDate" : "2020-10-21",
  "localDateTime" : "2020-10-21 17:58:22"
}

5.3 Joda日期

对于日期类型为 org.joda.time.DateTime,还需要添加代码 mapper.registerModule(new JodaModule()),同时添加相应的依赖 jar 包

    <dependency> 
      <groupId>com.fasterxml.jackson.datatype</groupId>
      <artifactId>jackson-datatype-joda</artifactId> 
      <version>2.9.10</version> 
    </dependency>

6 对象集合

Jackson 对泛型反序列化也提供很好的支持。

6.1 List

对于 List 类型 ,可以调用 constructCollectionType 方法来序列化,也可以构造 TypeReference 来序列化。

演示

@Test
public void test() throws IOException {
    ObjectMapper mapper = new ObjectMapper();

    // 造数据
    List<Student> list = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        Student student = new Student();
        student.setName("Tom");
        student.setAge(new Random().nextInt(100));
        student.setDate(new Date());
        list.add(student);
    }
    System.out.println("序列化");
    String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
    System.out.println(jsonInString);
    System.out.println("反序列化:使用 javaType");
    CollectionType javaType = mapper.getTypeFactory().constructCollectionType(List.class, Student.class);
    List<Student> personList = mapper.readValue(jsonInString, javaType);
    System.out.println(personList);
    System.out.println("反序列化:使用 TypeReference");
    List<Student> personList2 = mapper.readValue(jsonInString, new TypeReference<List<Student>>() {
    });
    System.out.println(personList2);
}
序列化
[ {
  "name" : "Tom",
  "age" : 40,
  "date" : 1603285233310,
  "height" : 0,
  "course" : null,
  "teacher" : null
}, {
  "name" : "Tom",
  "age" : 51,
  "date" : 1603285233310,
  "height" : 0,
  "course" : null,
  "teacher" : null
}, {
  "name" : "Tom",
  "age" : 87,
  "date" : 1603285233310,
  "height" : 0,
  "course" : null,
  "teacher" : null
} ]
反序列化:使用 javaType
[Student(name=Tom, age=40, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=51, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=87, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null)]
反序列化:使用 TypeReference
[Student(name=Tom, age=40, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=51, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null), Student(name=Tom, age=87, date=Wed Oct 21 21:00:33 CST 2020, height=0, course=null, teacher=null)]

6.2 Map

对于 map 类型, 与 List 的实现方式相似。

    public void test6() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        //第二参数是 map 的 key 的类型,第三参数是 map 的 value 的类型
        MapType javaType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Student.class);
        // 造数据
        Map<String, Student> map = new HashMap<>();
        for (int i = 0; i < 3; i++) {
            Student student = new Student();
            student.setName("Tom");
            student.setAge(new Random().nextInt(100));
            student.setDate(new Date());
            map.put("key" + i, student);
        }
        System.out.println("序列化");
        String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
        System.out.println(jsonInString);
        System.out.println("反序列化: 使用 javaType");
        Map<String, Student> personMap = mapper.readValue(jsonInString, javaType);
        System.out.println(personMap);
        System.out.println("反序列化: 使用 TypeReference");
        Map<String, Student> personMap2 = mapper.readValue(jsonInString, new TypeReference<Map<String, Student>>() {
        });
        System.out.println(personMap2);
    }
序列化
{
  "key1" : {
    "name" : "Tom",
    "age" : 44,
    "date" : 1603285404538,
    "height" : 0,
    "course" : null,
    "teacher" : null
  },
  "key2" : {
    "name" : "Tom",
    "age" : 44,
    "date" : 1603285404538,
    "height" : 0,
    "course" : null,
    "teacher" : null
  },
  "key0" : {
    "name" : "Tom",
    "age" : 2,
    "date" : 1603285404538,
    "height" : 0,
    "course" : null,
    "teacher" : null
  }
}
反序列化: 使用 javaType
{key1=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key2=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key0=Student(name=Tom, age=2, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null)}
反序列化: 使用 TypeReference
{key1=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key2=Student(name=Tom, age=44, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null), key0=Student(name=Tom, age=2, date=Wed Oct 21 21:03:24 CST 2020, height=0, course=null, teacher=null)}

7 属性可视化

JackSon 默认不是所有的属性都可以被序列化和反序列化。默认的属性可视化的规则如下:

  • 若该属性修饰符是 public,该属性可序列化和反序列化。

  • 若属性的修饰符不是 public,但是它的 getter 方法和 setter 方法是 public,该属性可序列化和反序列化。因为 getter 方法用于序列化, 而 setter 方法用于反序列化。

  • 若属性只有 public 的 setter 方法,而无 public 的 getter 方 法,该属性只能用于反序列化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值