Jackson的ObjectMapper使用

杨飞飙
2023-12-01

参考:
https://juejin.cn/post/6844904166809157639
https://blog.csdn.net/f641385712/category_10175312.html
https://juejin.cn/post/6844904113017192456

导入依赖

<!-- 根据自己需要引入相关版本依赖。 -->
 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-core</artifactId>
     <version>2.9.10</version>
 </dependency>

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

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

 <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.12</version>
 </dependency>

测试ObjectMapper

User

public class User implements Serializable {

    private String name;
    private Integer age;
    private int sex;
    private int height = 160;
    private Date birth;
    private boolean valid;

    /*private User user; // 不能自引用,否则write不出来

    public User() {

    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }*/

   /*  // 一些get和is方法,但是没有对应的属性
   public Object isHandsome() {
        return "帅";
    }

    public Object getXx() {
        return "123";
    }*/

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", height=" + height +
                ", birth=" + birth +
                ", valid=" + valid +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public boolean isValid() {
        return valid;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }


}

ObjectMapperTest

package com.zzhua;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.zzhua.pojo.User;
import org.junit.Before;
import org.junit.Test;

import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

public class ObjectMapperTest {

    User user;

    @Before
    public void init() {
        User user = new User();
        user.setName("曾zzhua");
        user.setAge(25);
        user.setSex(1);
        user.setHeight(55);
        user.setBirth(new Date());
        user.setValid(true);
        this.user = user;
    }

    @Test
    public void test_00() {
        ObjectMapper mapper = new ObjectMapper();
        String s = null;
        try {
            s = mapper.writeValueAsString(new User());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        /*{"name":null,"age":null,"sex":0,"height":160,"birth":null,"valid":false,"user":null}*/
        System.out.println(s);

        try {
            byte[] bytes = mapper.writeValueAsBytes(new User());
            /*{"name":null,"age":null,"sex":0,"height":160,"birth":null,"valid":false,"user":null}*/
            System.out.println(new String(bytes));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }



        // mapper.writeValue(Writer,Object);
        // mapper.writeValue(OutputStream, Object);
        // mapper.writeValue(File,Object);
        // mapper.writeValue(JsonGenerator, Object);



        ObjectWriter objectWriter = mapper.writerWithDefaultPrettyPrinter();
        try {
            /**
             // 输出
             {
                 "name" : "曾zzhua",
                 "age" : 25,
                 "sex" : 1,
                 "height" : 55,
                 "birth" : 1625897473042,
                 "valid" : true,
                 "user" : null
             }
             */
            String t = objectWriter.writeValueAsString(user);
            System.out.println(t);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }




    }

    @Test
    public void test_01() {
        ObjectMapper mapper = new ObjectMapper();
        String s = null;
        try {
            // user.setUser(user); // 注意:User中不能自引用,否则导致循环,抛出异常
            s = mapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(s); //{"name":"曾zzhua","age":25,"sex":1,"height":55,"birth":1625895996173,"valid":true}
    }

    @Test
    public void test_02() {
        ObjectMapper mapper = new ObjectMapper();

        // 开启序列化时的美化
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        String s = null;
        try {
            s = mapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        /*
          // 美化输出方式
          {
              "name" : "曾zzhua",
              "age" : 25,
              "sex" : 1,
              "height" : 55,
              "birth" : 1625896198831,
              "valid" : true
          }

        */
        System.out.println(s);
    }

    @Test
    public void test_03() {
        ObjectMapper mapper = new ObjectMapper();
        // 关闭自引用,但是还是不能直接设置本身,否则还是会递归下去
        mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
        String s = null;
        try {
            // user.setUser(new User()); // 注意:User中不能自引用,否则导致循环,抛出异常
            s = mapper.writeValueAsString(user);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(s);
    }

    @Test
    public void test_04() {
        ArrayList<User> list = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        list.add(user);
        list.add(new User());

        String s = null;
        try {
            /**
             * [ {
                  "name" : "曾zzhua",
                  "age" : 25,
                  "sex" : 1,
                  "height" : 55,
                  "birth" : 1625897250264,
                  "valid" : true,
                  "user" : null
                }, {
                  "name" : null,
                  "age" : null,
                  "sex" : 0,
                  "height" : 160,
                  "birth" : null,
                  "valid" : false,
                  "user" : null
                } ]
             */
            s = mapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(s);
    }

    @Test
    public void test_05() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();

        // 写一些其它的数据类型
        // 输出:1625901330439
        System.out.println(mapper.writeValueAsString(new Date()));

        // 输出:1
        System.out.println(mapper.writeValueAsString(1));
        // 输出:1
        System.out.println(mapper.writeValueAsString(new Integer(1)));

        // 输出:true
        System.out.println(mapper.writeValueAsString(true));
        // 输出:true
        System.out.println(mapper.writeValueAsString(Boolean.TRUE));

        // 输出:{"hour":15,"minute":16,"nano":412000000,"second":39,"dayOfMonth":10,
        // "dayOfWeek":"SATURDAY","month":"JULY","year":2021,"dayOfYear":191,
        // "monthValue":7,"chronology":{"id":"ISO","calendarType":"iso8601"}}
        System.out.println(mapper.writeValueAsString(LocalDateTime.now()));

        // 输出:"ab\u0003"
        char[] chars = {'a','b',3};
        System.out.println(mapper.writeValueAsString(chars));

        // 输出:""
        System.out.println(mapper.writeValueAsString(""));

        // 输出:null
        System.out.println(mapper.writeValueAsString(null));


    }

    @Test
    public void test_06() throws JsonProcessingException {
        // 给user添加了一个isHandsome()和getXx()方法,但是没有对应的属性
        ObjectMapper mapper = new ObjectMapper();
        String s = mapper.writeValueAsString(user);
        // 输出: {"name":"曾zzhua","age":25,"sex":1,"height":55,"birth":1625901740557,"valid":true,"xx":"123"}
        System.out.println(s);
    }

    @Test
    public void test_07() throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        /*{"name":null,"age":null,"sex":0,"height":160,"birth":null,"valid":false}*/
        String defaultUserStr = mapper.writeValueAsString(new User());
        System.out.println(defaultUserStr);

        // 读取默认user的字符串
        User defaultUser = mapper.readValue(defaultUserStr, User.class);
        // User{name='null', age=null, sex=0, height=160, birth=null, valid=false}
        System.out.println(defaultUser);

    }

    @Test
    public void test_08() throws IOException {


        ObjectMapper mapper = new ObjectMapper();

        // json字符串中少了个valid(布尔类型),看能不能读出来
        String userStr = "{\"name\":null,\"age\":null,\"sex\":0,\"height\":160,\"birth\":null}";

        // User{name='null', age=null, sex=0, height=160, birth=null, valid=false}
        User defaultUser = mapper.readValue(userStr, User.class);
        System.out.println(defaultUser);

        // json字符串中多了数据,能否读出来
        String userStr2 = "{\"name\":\"曾zzhua\",\"age\":25,\"sex\":1,\"height\":55,\"birth\":1625901740557,\"valid\":true,\"xx\":\"123\"}";
        // 报错!!!
        /*com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
          Unrecognized field "xx" (class com.zzhua.pojo.User), not marked as ignorable
          (6 known properties: "sex", "height", "name", "valid", "age", "birth"])
          at [Source: (String)"{"name":"曾zzhua","age":25,"sex":1,"height":55,
          "birth":1625901740557,"valid":true,"xx":"123"}"; line: 1, column: 88]
          (through reference chain: com.zzhua.pojo.User["xx"])*/
        // 这里有两种解决方案:
        // 1、mapper2.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 即可
        // 2、或者在类上添加注解@JsonIgnoreProperties(ignoreUnknown = true);即可
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        User user2 = mapper.readValue(userStr2, User.class);
        System.out.println(user2);

        // 如果用Object类型来接受,能获取到正确的类型么?
        Object o = mapper.readValue(userStr2, Object.class);
        // 输出:class java.util.LinkedHashMap
        System.out.println(o.getClass());
        // 输出:{name=曾zzhua, age=25, sex=1, height=55, birth=1625901740557, valid=true, xx=123}
        System.out.println(o);
        LinkedHashMap map = (LinkedHashMap) o;

        /* 输出:
            name   class java.lang.String 曾zzhua
            age    class java.lang.Integer 25
            sex    class java.lang.Integer 1
            height class java.lang.Integer 55
            birth  class java.lang.Long 1625901740557
            valid  class java.lang.Boolean true
            xx     class java.lang.String 123*/
        map.forEach((key,val)->{
            System.out.print(key + " ");
            System.out.print(val.getClass() + " ");
            System.out.println(val);
        });

    }

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

        // 全部没有,能否读出来
        String userStr = "{}";

        User defaultUser = mapper.readValue(userStr, User.class);
        // User{name='null', age=null, sex=0, height=160, birth=null, valid=false}
        System.out.println(defaultUser);


    }

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

        // 空字符串,能否读出来
        String userStr2 = "";

        // 报错!!!
        /*com.fasterxml.jackson.databind.exc.MismatchedInputException:
        No content to map due to end-of-input
        at [Source: (String)""; line: 1, column: 0]*/
        User defaultUser2 = mapper.readValue(userStr2, User.class);
        System.out.println(defaultUser2);


    }

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

        // null,能否读出来
        String userStr = null;

        // 报错,空指针异常
        User defaultUser = mapper.readValue(userStr, User.class);
        System.out.println(defaultUser);
    }

    @Test
    public void test_12() {
        LocalDateTime now = LocalDateTime.now();
        ObjectMapper mapper = new ObjectMapper();
        try {
            String s = mapper.writeValueAsString(now);
            System.out.println(s);
            /* 报错
            * com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
            * Cannot construct instance of `java.time.LocalDateTime`
            * (no Creators, like default construct, exist): cannot deserialize from Object value
            * (no delegate- or property-based Creator)
               at [Source: (String)"{"dayOfMonth":10,"dayOfWeek":"SATURDAY","month":"JULY",
               "year":2021,"dayOfYear":191,"hour":16,"minute":58,"monthValue":7,
               "nano":869000000,"second":42,"chronology":{"id":"ISO","calendarType":"iso8601"}}";
               line: 1, column: 2]
            * */
            LocalDateTime localDateTime = mapper.readValue(s, LocalDateTime.class);
            System.out.println(localDateTime);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test_13() throws IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        // 输出:{"name":"曾zzhua","age":25,"sex":1,"height":55,"birth":1636788268941,"valid":true}
        String userJson = objectMapper.writeValueAsString(user);
        System.out.println(userJson);

        User user = objectMapper.readValue(userJson, User.class);
        // 输出:User{name='曾zzhua', age=25, sex=1, height=55, birth=Sat Nov 13 15:27:11 CST 2021, valid=true}
        System.out.println(user);

        Map map = objectMapper.readValue(userJson, Map.class);
        /*
        输出:
            【name->曾zzhua】-       【class java.lang.String->class java.lang.String】
            【age->25】-             【class java.lang.String->class java.lang.Integer】
            【sex->1】-              【class java.lang.String->class java.lang.Integer】
            【height->55】-          【class java.lang.String->class java.lang.Integer】
            【birth->1636788723062】-【class java.lang.String->class java.lang.Long】
            【valid->true】-         【class java.lang.String->class java.lang.Boolean】
        */
        map.forEach((k,v)->{
            System.out.println("【"+k +"->"+ v + "】-【" + k.getClass() + "->" + v.getClass() +"】");
        });

    }
	@Test
    public void test_14() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        String dateStr = objectMapper.writeValueAsString(new Date());
        System.out.println(dateStr); // 输出:1636789190919
        Date date = objectMapper.readValue(dateStr, Date.class);
        System.out.println(date);    // 输出:Sat Nov 13 15:39:50 CST 2021

    }

    @Test
    public void testSaveObject() {
        // 创建user对象
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        System.out.println(now.hashCode());

        // 使用ObjectOutputStream包装ByteArrayOutputStream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(baos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 使用ObjectOutputStream写对象
            oos.writeObject(now);
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] userBytes = baos.toByteArray();

        // 使用ObjectInputStream包装ByteArrayInputStream
        ByteArrayInputStream bais = new ByteArrayInputStream(userBytes);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(bais);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            // 使用ObjectInputStream读取对象
            Object o = ois.readObject();
            System.out.println(o.getClass());
            System.out.println(o);
            System.out.println(o.hashCode());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

	// 测试反序列化数组json
	@Test
    public void testDeserializeArray() {

        Person p1 = new Person("zzhua",25);
        Person p2 = new Person("zj",24);
        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);

        ObjectMapper mapper = new ObjectMapper();
        String personListJson = mapper.writeValueAsString(list);
        System.out.println(personListJson); // [{"name":"zzhua","age":25},{"name":"zj","age":24}]

        TypeFactory typeFactory = mapper.getTypeFactory();
        JavaType javaType = typeFactory.constructParametricType(List.class, Person.class);
        List<Person> personList = mapper.readValue(personListJson, javaType);
        System.out.println(personList); // [PropertyUtil.Person(name=zzhua, age=25), PropertyUtil.Person(name=zj, age=24)]


        List<Person> personList2 = mapper.readValue(personListJson, new TypeReference<List<Person>>(){});
        System.out.println(personList2); //[PropertyUtil.Person(name=zzhua, age=25), PropertyUtil.Person(name=zj, age=24)]


    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Person {
        private String name;
        private Integer age;
    }
}




来源:https://juejin.cn/post/6844904113017192456

基本使用

反序列化

1、使用ObjectMapper,将json字符串转成对象:

String str = "{\"id\":1,\"name\":\"haha\",\"elements\":[{\"age\":1,\"elName\":\"zll\"},{\"age\":2,\"elName\":\"zll1\"}]}";
ObjectMapper objectMapper = new ObjectMapper();
TestBean testBean = objectMapper.readValue(str, TestBean.class);
System.out.println(testBean.toString());
// 输出:TestBean(id=1, name=haha, elements=[Element(age=1, elName=zll), Element(age=2, elName=zll1)])

2、使用ObjectMapper,读取json某些字段值

String str = "{\"id\":1,\"name\":\"haha\",\"elements\":[{\"age\":1,\"elName\":\"zll\"},{\"age\":2,\"elName\":\"zll1\"}]}";
 ObjectMapper objectMapper = new ObjectMapper();
 JsonNode jsonNode = objectMapper.readTree(str);
 //获取name字段值
 JsonNode name = jsonNode.get("name");
 String s = name.asText();
 System.out.println(s);
 //获取elements字段下数组第二个对象的age
 JsonNode elements = jsonNode.get("elements");
 JsonNode object2 = elements.get(1);//从0开始哦
 JsonNode age = object2.get("age");
 int i = age.asInt();
 System.out.println(i);
 // 输出:haha 2

序列化

ObjectMapper(将JavaObject转化成JSON)

Element element = new Element();
element.setAge(1);
element.setElName("zll");
ObjectMapper objectMapper = new ObjectMapper();
String elementStr = objectMapper.writeValueAsString(element);
System.out.println(elementStr);
// 输出:{"age":1,"elName":"zll"}

其他常用序列化方法:

writeValue(File arg0, Object arg1)把arg1转成json序列,并保存到arg0文件中
writeValue(OutputStream arg0, Object arg1)把arg1转成json序列,并保存到arg0输出流中。
teValueAsBytes(Object arg0)把arg0转成json序列,并把结果输出成字节数组
writeValueAsString(Object arg0)把arg0转成json序列,并把结果输出成字符串。

JsonGenerator(json生成器):

可以根据自己的需要创建相应结构的json

ByteArrayOutputStream bout = new ByteArrayOutputStream();
//JsonFactory jsonFactory = new JsonFactory();
//创建jsonfactory 2种方法
ObjectMapper objectMapper = new ObjectMapper();
JsonFactory jsonFactory = objectMapper.getFactory();
JsonGenerator generator = jsonFactory.createGenerator(bout);
//创建自己需要的json
//创建对象获取数组要写开始和结束
generator.writeStartObject();
    //创建一个字段 第一个参数key 第二个参数value
    generator.writeStringField("name","value");
    generator.writeNumberField("numberName",1);
    //或者直接创建object
    generator.writeObjectField("ObjectName","ObjectValue");
    //创建数组
    generator.writeArrayFieldStart("arrayName");
        //里面可以是对象、数组、字符串、数字
        generator.writeString("element1");
        generator.writeNumber(1);
        generator.writeNumber(1);
    generator.writeEndArray();
generator.writeEndObject();
generator.flush();
generator.close();
String s = bout.toString();
System.out.println(s);
// 输出:{"name":"value","numberName":1,"ObjectName":"ObjectValue","arrayName":["element1",1,1]}

ObjectMapper的常用设置

ObjectMapper objectMapper = new ObjectMapper();  
 
//序列化的时候序列对象的所有属性  
objectMapper.setSerializationInclusion(Include.ALWAYS);  
 
//反序列化的时候如果多了其他属性,不抛出异常  
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);  
 
//如果是空对象的时候,不抛异常  
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);  
 
//属性为null的转换
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
 
//取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式  
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);  
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

常用注解


@JsonIgnoreProperties(ignoreUnknown = true):
将这个注解加载类上,不存在的字段将被忽略。


@JsonIgnoreProperties({ “password”, “secretKey” }):
指定忽略字段


@JsonIgnore:
标在注解上,将忽略此字段


@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”):
标在时间自端上序列化是使用制定规则格式化(默认转化成时间戳)


@JsonInclude(参数)
JsonInclude.Include.NON_EMPTY:属性为空或者null都不参与序列化
JsonInclude.Include.NON_NULL:属性为null不参与序列化


@JsonProperty("firstName")
标在字段上,指定序列化后的字段名


@JsonDeserialize(using= T extends JsonDeserializer.class)和@JsonSerialize(using= T extends     JsonSerializer.class)
自定义某些类型字段的序列化与反序列化规则

还有很多的注解在:
com.fasterxml.jackson.annotation包下:
@JacksonAnnotation
@JacksonAnnotationsInside
@JacksonAnnotationValue
@JacksonInject
@JsonAlias
@JsonAnyGetter
@JsonAnySetter
@JsonAutoDetect
@JsonBackReference
@JsonClassDescription
@JsonCreator
@JsonEnumDefaultValue
@JsonFilter
@JsonFormat
@JsonGetter
@JsonIdentityInfo
@JsonIdentityReference
@JsonIgnore
@JsonIgnoreProperties
@JsonIgnoreType
@JsonInclude
@JsonManagedReference
@JsonMerge
@JsonProperty
@JsonPropertyDescription
@JsonPropertyOrder
@JsonRawValue
@JsonRootName
@JsonSetter
@JsonSubTypes
@JsonTypeId
@JsonTypeInfo
@JsonTypeName
@JsonUnwrapped
@JsonValue
@JsonView
在com.fasterxml.jackson.databind.annotation包下:
@JacksonStdImpl
@JsonAppend
@JsonDeserialize
@JsonNaming
@JsonPOJOBuilder
@JsonSerialize
@JsonTypeIdResolver
@JsonTypeResolver
@JsonValueInstantiator
 类似资料: