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;