相关文章推荐
豪情万千的骆驼  ·  Using the Java APIs ...·  5 月前    · 
豪情万千的眼镜  ·  Hosting the WCF ...·  1 年前    · 
旅行中的包子  ·  pickle & cPickle ...·  1 年前    · 

Java生态圈中有很多处理JSON和XML格式化的类库,Jackson是其中比较著名的一个。Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架。Jackson 社区相对比较活跃,更新速度也比较快。

Spring MVC 的默认 json 解析器便是 Jackson 。 Jackson 优点很多, Jackson 所依赖的 jar 包较少 ,简单易用。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json文件速度比较快;Jackson运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。

Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson 。本文讨论的内容是基于Jackson 的 2.9.1 版本。

Jackson 的核心模块

  • jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json;
  • jackson-annotations,注解包,提供标准注解功能;
  • jackson-databind,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API;
  • <dependency> 
        <groupId>com.fasterxml.jackson.core</groupId> 
        <artifactId>jackson-databind</artifactId> 
        <version>2.9.1</version> 
    </dependency>
    <!-- 支持xml格式 -->
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.9.1</version>
    </dependency>

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

    ObjectMapper的使用

    Jackson 最常用的 API 就是基于"对象绑定" 的 ObjectMapper 。下面是一个 ObjectMapper 的使用的简单示例:

    ObjectMapper mapper = new ObjectMapper(); 
    Person person = new Person(); 
    person.setName("Tom"); 
    person.setAge(40); 
    String jsonString = mapper.writerWithDefaultPrettyPrinter() 
    .writeValueAsString(person); 
    Person deserializedPerson = mapper.readValue(jsonString, Person.class);

    先创建一个ObjectMapper,然后赋值一些属性:

    public static ObjectMapper mapper = new ObjectMapper();
    static {
        // 转换为格式化的json
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 如果json中有新增的字段并且是实体类类中不存在的,不报错
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    

    创建一个实体类:

    public class XwjUser implements Serializable {
        private static final long serialVersionUID = 1L;
        private int id;
        private String message;
        private Date sendTime;
        // 这里手写字母大写,只是为了测试使用,是不符合java规范的
        private String NodeName;
        private List<Integer> intList;
        public XwjUser() {
            super();
        public XwjUser(int id, String message, Date sendTime) {
            super();
            this.id = id;
            this.message = message;
            this.sendTime = sendTime;
        public int getId() {
            return id;
        public void setId(int id) {
            this.id = id;
        public String getMessage() {
            return message;
        public void setMessage(String message) {
            this.message = message;
        public Date getSendTime() {
            return sendTime;
        public void setSendTime(Date sendTime) {
            this.sendTime = sendTime;
        public String getNodeName() {
            return NodeName;
        public void setNodeName(String nodeName) {
            NodeName = nodeName;
        public List<Integer> getIntList() {
            return intList;
        public void setIntList(List<Integer> intList) {
            this.intList = intList;
        @Override
        public String toString() {
            return "XwjUser [id=" + id + ", message=" + message + ", sendTime=" + sendTime + ", intList=" + intList + "]";
    

    对象与json字符串、byte数组

    XwjUser user = new XwjUser(1, "Hello World", new Date());
    mapper.writeValue(new File("D:/test.txt"), user); // 写到文件中
    // mapper.writeValue(System.out, user); //写到控制台
    String jsonStr = mapper.writeValueAsString(user);
    System.out.println("对象转为字符串:" + jsonStr);
    byte[] byteArr = mapper.writeValueAsBytes(user);
    System.out.println("对象转为byte数组:" + byteArr);
    XwjUser userDe = mapper.readValue(jsonStr, XwjUser.class);
    System.out.println("json字符串转为对象:" + userDe);
    XwjUser useDe2 = mapper.readValue(byteArr, XwjUser.class);
    System.out.println("byte数组转为对象:" + useDe2);

    注意,对象转json字符串时,对象中的NodeName首字母是大写,转出来是小写。

    list集合与json字符串

    List<XwjUser> userList = new ArrayList<>();
    userList.add(new XwjUser(1, "aaa", new Date()));
    userList.add(new XwjUser(2, "bbb", new Date()));
    userList.add(new XwjUser(3, "ccc", new Date()));
    userList.add(new XwjUser(4, "ddd", new Date()));
    String jsonStr = mapper.writeValueAsString(userList);
    System.out.println("集合转为字符串:" + jsonStr);
    List<XwjUser> userListDes = mapper.readValue(jsonStr, List.class);
    System.out.println("字符串转集合:" + userListDes);

    map与json字符串

    Map<String, Object> testMap = new HashMap<>();
    testMap.put("name", "merry");
    testMap.put("age", 30);
    testMap.put("date", new Date());
    testMap.put("user", new XwjUser(1, "Hello World", new Date()));
    try {
        String jsonStr = mapper.writeValueAsString(testMap);
        System.out.println("Map转为字符串:" + jsonStr);
        try {
            Map<String, Object> testMapDes = mapper.readValue(jsonStr, Map.class);
            System.out.println("字符串转Map:" + testMapDes);
        } catch (IOException e) {
            e.printStackTrace();
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    

    修改转换时的日期格式

    // 修改时间格式
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    XwjUser user = new XwjUser(1, "Hello World", new Date());
    user.setIntList(Arrays.asList(1, 2, 3));
    String jsonStr = mapper.writeValueAsString(user);
    System.out.println("对象转为字符串:" + jsonStr);

    Jackson注解

    序列化注解

    @JsonAnyGetter

    该注解用于把可变的Map类型属性当做标准属性

    ExtendableBean实体有一个name属性和一组key/value格式的可扩展属性:

    public class ExtendableBean {
        public String name;
        public Map<String, String> properties;
        @JsonAnyGetter
        public Map<String, String> getProperties() {
            return properties;
        public ExtendableBean(String name) {
            this.name = name;
            properties = new HashMap<>();
        public void add(String key, String value){
            properties.put(key, value);
    

    下面是把ExtendableBean实体序列化的过程:

    private static void whenSerializingUsingJsonAnyGetter_thenCorrect(){
        ExtendableBean bean = new ExtendableBean("My bean");
        bean.add("attr1", "val1");
        bean.add("attr2", "val2");
        String result = null;
        try {
            result = new ObjectMapper().writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        System.out.println(result);
    

    序列化后的结果: {"name":"My bean","attr2":"val2","attr1":"val1"}

    @JsonGetter

    该注解是@JsonProperty的两个作用中的一个, 用来标记一个方法是getter方法。

    下例中, 指定方法getTheName()是属性name属性的getter方法

    public class MyBean {
        public int id;
        private String name;
        @JsonGetter("name")
        public String getTheName() {
            return name;
    

    下面是序列化过程

    public void whenSerializingUsingJsonGetter_thenCorrect()
      throws JsonProcessingException {
        MyBean bean = new MyBean(1, "My bean");
        String result = new ObjectMapper().writeValueAsString(bean);
    

    @JsonPropertyOrder

    该注解可以指定实体属性序列化后的顺序

    @JsonPropertyOrder({ "name", "id" })
    public class MyBean {
        public int id;
        public String name;
    

    序列化后的结果:{ "name":"My bean", "id":1}

    该注解有一个参数alphabetic, 如果为true, 表示按字母顺序序列化,此时输出结果:{ "id":1, "name":"My bean"}

    @JsonRawValue

    该注解可以让Jackson在序列化时把属性的值原样输出。

    下面的例子中, 我们给实体属性attrs赋值一个json字符串

    public class RawBean {
        public String name;
        @JsonRawValue
        public String attrs;
    public void whenSerializingUsingJsonRawValue_thenCorrect()
      throws JsonProcessingException {  
        RawBean bean = new RawBean("My bean", "{\"attr\":false}");
        String result = new ObjectMapper().writeValueAsString(bean);
    

    输出结果是: {"name":"Mybean","attrs":{"attr":false}}。

    @JsonValue

    该注解作用于一个方法, 并且只用被注解的方法序列化整个实体对象。

    class ExtendableBean {
       ...........
       //把注解换成JsonValue
        @JsonValue
        public Map<String, String> getProperties() {
            return properties;
        ..........
    

    序列化过程不变, 则结果是: {"attr2":"val2","attr1":"val1"}

    可见, 属性name没有被序列化。

    @JsonRootName

    该注解用来指定root wrapper的名称

    wrapping(包装)的含义是如果序列化实体User的结果是:

    "id": 1, "name": "John"

    那么wrapping后的效果如下:

    "User": { "id": 1, "name": "John"

    下面看一个例子, 我们用该注解指明包装实体(wrapper entity)的包装器名称:

    @JsonRootName(value = "user")
    public class UserWithRoot {
        public int id;
        public String name;
    

    包装器默认名称是实体类名, 这里就是UserWithRoot, 但是注解的value属性把包装器名称改为了user。

    序列化过程(和前面不同, 需要使用包装器)

    private static void whenSerializingUsingJsonRootName_thenCorrect(){
        UserWithRoot user = new UserWithRoot();
        user.id = 1;
        user.name = "jackma";
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
            String result = objectMapper.writeValueAsString(user);
            System.out.println(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
    

    序列化的结果:{"user":{"id":1,"name":"jackma"}}

    从Jackson2.4版本开始, 新增了一个可选参数namespace, 该属性对json没效果, 但是对xml起作用, 修改本例的实体例:

    @JsonRootName(value = "user", namespace = "alibaba")
    class UserWithRoot {
        public int id;
        public String name;
    

    用XmlMapper序列化:

    private static void whenSerializingUsingJsonRootName_thenCorrect(){
        ..............
            XmlMapper xmlMapper = new XmlMapper();
            xmlMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        ..............

    序列化结果:

    <user xmlns="alibaba">
        <id xmlns="">1</id>
        <name xmlns="">jackma</name>
    </user>

    @JsonSerialize

    该注解用于指定一个自定义序列化器(custom serializer)来序列化实体例的某属性

    下例中, 用@JsonSerialize的参数using指明实体类属性eventDate的序列化器是CustomDateSerializer类:

    public class Event {
        public String name;
        @JsonSerialize(using = CustomDateSerializer.class)
        public Date eventDate;
    

    下面是类CustomDateSerializer的定义:

    public class CustomDateSerializer extends StdSerializer<Date> {
        private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
        public CustomDateSerializer() { this(null); } 
        public CustomDateSerializer(Class<Date> t) { super(t); }
        @Override
        public void serialize(Date value, JsonGenerator gen, SerializerProvider arg2) 
            throws IOException, JsonProcessingException {
            gen.writeString(formatter.format(value));
    
    public void whenSerializingUsingJsonSerialize_thenCorrect(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/DD hh:mm:ss");
        String toParse = "2019/08/19 16:28:00";
        Date date = null;
        try {
            date = df.parse(toParse);
        } catch (ParseException e) {
            e.printStackTrace();
        Event event = new Event();
        event.name = "party";
        event.eventDate = date;
        try {
            String result = new ObjectMapper().writeValueAsString(event);
            System.out.println(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
    

    序列化结果: {"name":"party","eventDate":"2019-08-19 04:28:00"}

    而如果没有@JsonSerialize注解的序列化结果是: {"name":"party","eventDate":1566203280000}

    如果想将整型转换为字符串,可以使用:@JsonSerialize(using = ToStringSerializer.class)

    反序列化注解

    @JsonCreator

    该注解可以调整反序列化时构造器/构造工厂的行为。

    当我们需要反序列化的Json字符串和目标实体类不完全匹配时, 这个注解非常有用。

    假设我们要反序列化下面的Json字符串:

    "id":1, "theName":"My bean"

    但是, 我们的目标实体类并没有一个名为theName的属性。现在, 我们不想改变实体类本身, 我们只需在数据导出时做一些控制, 方法就是在构造器中使用@JsonCreator和@JsonProperty注解:

    public class BeanWithCreator {
        public int id;
        public String name;
        @JsonCreator
        public BeanWithCreator(
          @JsonProperty("id") int id, 
          @JsonProperty("theName") String name) {
            this.id = id;
            this.name = name;
    

    反序列化过程:

    String json = "{\"id\":1,\"theName\":\"My bean\"}";
    BeanWithCreator bean = new ObjectMapper().readerFor(BeanWithCreator.class).readValue(json);

    @JacksonInject

    该注解指明一个属性的值是通过注入得到而不是从Json字符串反序列得到。

    下例的实体例属性id的值用注解标明是注入值:

    public class BeanWithInject {
        @JacksonInject
        public int id;
        public String name;
    

    反序列化过程:

    String json = "{\"name\":\"My bean\"}";     
    InjectableValues inject = new InjectableValues.Std().addValue(int.class, 1);
    BeanWithInject bean = new ObjectMapper().reader(inject).forType(BeanWithInject.class).readValue(json);

    @JsonAnySetter

    该注解允许我们把一个可变的map属性作为标准属性, 在反序列过程中, 从Json字符串得到的属性值会加入到map属性中 实体例和注解:

    public class ExtendableBean {
        public String name;
        private Map<String, String> properties;
        @JsonAnySetter
        public void add(String key, String value) {
            properties.put(key, value);
    

    准备反序列化的Json字符串:

    "name":"My bean", "attr2":"val2", "attr1":"val1"

    反序列化过程:

    String json = "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}"; 
    ExtendableBean bean = new ObjectMapper().readerFor(ExtendableBean.class).readValue(json);   

    @JsonSetter

    该注解是@JsonProperty的另一个作用, 和@JsonGetter相对, 标记一个方法是setter方法。

    如果目标实体类没有和Json字符串数据完全匹配的方法时, 我们可以通过这个注解做一些调整让他们匹配。

    下例中指定方法setTheName()作为name属性的setter方法

    public class MyBean {
        public int id;
        private String name;
        @JsonSetter("name")
        public void setTheName(String name) {
            this.name = name;
    

    反序列化过程:

    String json = "{\"id\":1,\"name\":\"My bean\"}"; 
    MyBean bean = new ObjectMapper().readerFor(MyBean.class).readValue(json);

    @JsonDeserialize

    该注解标明使用自定义反序列化器(custom deserializer)。

    public class Event {
        public String name;
        @JsonDeserialize(using = CustomDateDeserializer.class)
        public Date eventDate;
    

    自定义反序列化器:

    public class CustomDateDeserializer  extends StdDeserializer<Date> { 
        private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
         public CustomDateDeserializer() { 
            this(null); 
        public CustomDateDeserializer(Class<?> vc) { 
            super(vc); 
        @Override
        public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {         
            String date = jsonparser.getText();
            try {
                return formatter.parse(date);
            } catch (ParseException e) {
                throw new RuntimeException(e);
    

    反序列化过程:

    String json = "{"name":"party","eventDate":"20-12-2014 02:30:00"}"; 
    SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
    Event event = new ObjectMapper().readerFor(Event.class).readValue(json);     
    assertEquals("20-12-2014 02:30:00", df.format(event.eventDate));

    @JsonAlias

    该注解在反序列化过程中为属性定义一个或多个别名。

    public class AliasBean {
        @JsonAlias({ "fName", "f_name" })
        private String firstName;   
        private String lastName;
    

    Json字符串中fName, f_name或firstName的值都可以被反序列到属性firstName

    String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";
    AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
    assertEquals("John", aliasBean.getFirstName());

    属性包含注解

    @JsonIgnoreProperties

    该注解是一个类级别的注解, 标记一个或多个属性被Jackson忽略。

    @JsonIgnoreProperties({ "id" })
    public class BeanWithIgnore {
        public int id;
        public String name;
    

    参数ignoreUnknown为true时, Json字符串如果有未知的属性名, 则不会抛出异常。

    @JsonIgnore

    该注解用于属性级别, 用于标明一个属性可以被Jackson忽略。

    public class BeanWithIgnore {
        @JsonIgnore
        public int id;
        public String name;
    

    @JsonIgnoreType

    该注解标记类型是注解作用的类型的属性都会被忽略

    必须作用于类, 标明以该类为类型的属性都会被Jackson忽略

    public class User {
        public int id;
        public Name name;
        @JsonIgnoreType
        public static class Name {
            public String firstName;
            public String lastName;
    

    @JsonInclude

    该注解在序列化时会排除属性值是空值(empty或null)、没有默认值的属性。

    可作用在类和属性上。

    @JsonInclude(Include.NON_NULL)
    public class MyBean {
        public int id;
        public String name;
    

    @JsonAutoDetect

    该注解可以覆盖属性是否可见的默认语义, 比如对于不可见的private序列化时变成可见的。

    @JsonAutoDetect(fieldVisibility = Visibility.ANY)
    public class PrivateBean {
        private int id;
        private String name;
    

    @JsonProperty

    该注解可以指定属性在Json字符串中的名字。

    下例中在非标准的setter和getter方法上使用该注解, 可以成功序列化和反序列化:

    public class MyBean {
        public int id;
        private String name;
        @JsonProperty("name")
        public void setTheName(String name) {
            this.name = name;
        @JsonProperty("name")
        public String getTheName() {
            return name;
    

    @JsonFormat

    该注解指定序列化日期和时间时的格式。

    public class Event {
        public String name;
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
        public Date eventDate;
    

    序列化过程:

    SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    String toParse = "20-12-2014 02:30:00";
    Date date = df.parse(toParse);
    Event event = new Event("party", date);     
    String result = new ObjectMapper().writeValueAsString(event);     
    assertThat(result, containsString(toParse));

    @JsonUnwrapped

    该注解指定值在序列化和反序列化时, 去除对应属性的外包装(根节点)

    public class UnwrappedUser {
        public int id;
        @JsonUnwrapped
        public Name name;
        public static class Name {
            public String firstName;
            public String lastName;
    

    @JsonFilter

    该注解可以在序列化时指定一个过滤器。

    下面为一个实体类指定一个过滤器:

    @JsonFilter("myFilter")
    public class BeanWithFilter {
        public int id;
        public String name;
    

    定义过滤器并进行序列化

    BeanWithFilter bean = new BeanWithFilter(1, "My bean"); 
    FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",    
                            SimpleBeanPropertyFilter.filterOutAllExcept("name")); 
    String result = new ObjectMapper().writer(filters).writeValueAsString(bean);

    序列化结果:{"name":"My bean"}

    这里添加了一个SimpleBeanPropertyFilter.filterOutAllExcept过滤器, 该过滤器的含义是除name属性外, 其他属性都被过滤掉(不序列化)。

    @JsonAppend

    该注解用来给一个被序列化的对象添加一个虚拟属性。这个功能非常有用, 尤其是当我们想直接在Json字符串中添加额外的信息时, 不再需要修改类的定义。

    举例来说, 它可以很方便的在Json文档中插入bean的版本信息, 而不需要bean提供对应的属性。

    使用@JsonAppend注解的实体类:

    @JsonAppend(attrs = {@JsonAppend.Attr(value = "version")})
    public class BeanWithAppend {
        private int id;
        private String name;
        // constructor, getters and setters
    

    序列化过程:

    BeanWithAppend bean = new BeanWithAppend(2, "Bean With Append Annotation");
    ObjectWriter writer = mapper.writerFor(BeanWithAppend.class).withAttribute("version", "1.0");
    String jsonString = writer.writeValueAsString(bean);

    序列化结果: { "id": 2, "name": "Bean With Append Annotation", "version": "1.0" }

    @JsonNaming

    该注解用来在序列化时选择一个属性命名习惯来代替默认属性名。注解参数value用来指定已有命名习惯, 或用户定义的命名习惯。除默认值(value=LOWER_CAMEL_CASE, 即驼峰命名法)外, Jackson库同时提供了4种内置的属性命名习惯:

  • KEBAB_CASE: 属性名单词用短线分隔连接, 比如hello-world
  • LOWER_CASE: 属性名用小写字母而且没有分隔符, 比如helloworld
  • SNAKE_CASE: 属性名用小写字母而且用下划线做分隔符, 比如hello_world
  • UPPER_CAMEL_CASE: 属性名所有单词用大写开头而且没有分隔符, 比如HelloWorld
  • 下例中用SNAKE_CASE命名法, 将属性beanName名序列化为bean_name

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    public class NamingBean {
        private int id;
        private String beanName;
        // constructor, getters and setters
    

    序列化过程:

    NamingBean bean = new NamingBean(3, "Naming Bean");
    String jsonString = mapper.writeValueAsString(bean);  

    序列化结果: { "id": 3, "bean_name": "Naming Bean" }

    禁用Jackson注解

    通过设置MapperFeature.USE_ANNOTATIONS可以禁用实体类上的Jackson注解。

    @JsonInclude(Include.NON_NULL)
    @JsonPropertyOrder({ "name", "id" })
    public class MyBean {
        public int id;
        public String name;
    

    序列化过程

    MyBean bean = new MyBean(1, null); 
    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.USE_ANNOTATIONS);
    String result = mapper.writeValueAsString(bean);

    序列化结果:{ "id":1, "name":null}

    如果注释掉mapper.disable(MapperFeature.USE_ANNOTATIONS);, 则序列化结果是: {"id":1}

    Jackson工具类

    @Slf4j
    public class JsonUtil {
        private static ObjectMapper objectMapper = new ObjectMapper();
        // 日起格式化
        private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
        static {
            //对象的所有字段全部列入
            objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
            //取消默认转换timestamps形式
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            //忽略空Bean转json的错误
            objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            //所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
            objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
            //忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         * 对象转Json格式字符串
         * @param obj 对象
         * @return Json格式字符串
        public static <T> String obj2String(T obj) {
            if (obj == null) {
                return null;
            try {
                return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                log.warn("Parse Object to String error : {}", e.getMessage());
                return null;
         * 对象转Json格式字符串(格式化的Json字符串)
         * @param obj 对象
         * @return 美化的Json格式字符串
        public static <T> String obj2StringPretty(T obj) {
            if (obj == null) {
                return null;
            try {
                return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                log.warn("Parse Object to String error : {}", e.getMessage());
                return null;
         * 字符串转换为自定义对象
         * @param str   要转换的字符串
         * @param clazz 自定义对象的class对象
         * @return 自定义对象
        public static <T> T string2Obj(String str, Class<T> clazz) {
            if (StringUtils.isEmpty(str) || clazz == null) {
                return null;
            try {
                return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
            } catch (Exception e) {
                log.warn("Parse String to Object error : {}", e.getMessage());
                return null;
        public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
            if (StringUtils.isEmpty(str) || typeReference == null) {
                return null;
            try {
                return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference));
            } catch (IOException e) {
                log.warn("Parse String to Object error", e);
                return null;
        public static <T> T string2Obj(String str, Class<?> collectionClazz, Class<?>... elementClazzes) {
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClazz, elementClazzes);
            try {
                return objectMapper.readValue(str, javaType);
            } catch (IOException e) {
                log.warn("Parse String to Object error : {}" + e.getMessage());
                return null;