高效的JSON和Java对象转换类库Jackson

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;
        }
    }
}

 

posted @ 2022-01-05 17:00  残城碎梦  阅读(508)  评论(0编辑  收藏  举报