Jackson
Spring MVC的默认JSON解析器也是Jackson。
Jackson 引入依赖的jar包:
<!--jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.1</version> </dependency>
jackson-databind 依赖 jackson-core 和 jackson-annotations,根据依赖传递性,当添加 jackson-databind 之后, jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中,因此无需再单独添加jackson-core 和 jackson-annotations
简单用法使用步骤:
第1步:创建ObjectMapper对象
创建ObjectMapper对象。它是一个可重复使用的对象。
ObjectMapper mapper = new ObjectMapper();
第2步:反序列化JSON到对象
从JSON对象使用readValue()方法来获取。通过JSON字符串和对象类型作为参数JSON字符串/来源。
//Object to JSON Conversion
Student student = mapper.readValue(jsonString, Student.class);
第3步:序列化对象到JSON
使用writeValueAsString()方法来获取对象的JSON字符串表示。
//Object to JSON Conversion
jsonString = mapper.writeValueAsString(student);
ObjectMapper
ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写
1)ObjectMapper 通过 writeValue 系列方法 将 java 对 象序列化 为 json,并 将 json 存 储成不同的格式,String(writeValueAsString),Byte Array(writeValueAsString),Writer, File,OutStream 和 DataOutput。
2)ObjectMapper 通过 readValue 系列方法从不同的数据源像 String , Byte Array, Reader,File,URL, InputStream 将 json 反序列化为 java 对象
ObjectMapper 的一些相关配置:
//在反序列化时忽略在 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) //在序列化时忽略值为 null 的属性 mapper.setSerializationInclusion(Include.NON_NULL); //忽略值为默认值的属性 mapper.setDefaultPropertyInclusion(Include.NON_DEFAULT);
Jackson的注解使用
注解 | 用法 |
---|---|
@JsonProperty | 用于属性,把属性的名称序列化时转换为另外一个名称,及在反序列化时将指定名称的字段反序列化到当前字段上。示例: @JsonProperty(“birth_ d ate”) private Date birthDate; |
@JsonFormat | 用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) public Date getBirthDate() |
@JsonPropertyOrder | 用于类, 指定属性在序列化时 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; } |
泛型反序列化
对于 List 类型 ,可以调用 constructCollectionType 方法来序列化,也可以构造 TypeReference 来序列化
CollectionType javaType = mapper.getTypeFactory().constructCollectionType(List.class,Person.class); List<Person> personList = mapper.readValue(jsonInString,javaType); List<Person> personList = mapper.readValue(jsonInString, new TypeReference<List<Person>>(){});
map 类型, 与 List 的实现方式相似,Map 泛型使用示例:
//第二参数是 map 的 key 的类型,第三参数是 map 的 value 的类型 MapType javaType =mapper.getTypeFactory().constructMapType(HashMap.class,String.class,Person.class); Map<String, Person> personMap = mapper.readValue(jsonInString,javaType); Map<String, Person> personMap = mapper.readValue(jsonInString, new TypeReference<Map<String, Person>>() {});
属性可视化
默认的属性可视化规则如下:
1)若该属性修饰符是 public,该属性可序列化和反序列化
2)若属性的修饰符不是 public,但是它的 getter 方法和 setter 方法是 public,该属性可序列化和反序列化。因为 getter 方法用于序列化, 而 setter 方法用于反序列化
3)若属性只有 public 的 setter 方法,而无 public 的 getter 方 法,该属性只能用于反序列化
若想更改默认的属性可视化的规则,需要调用 ObjectMapper 的方法 setVisibility。
如使修饰符为protected的属性name也可以序列化和反序列化:
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); public class Person { public int age; protected String name; } // PropertyAccessor 支持的类型有: ALL,CREATOR,FIELD,GETTER,IS_GETTER,NONE,SETTER // Visibility 支持的类型有: ANY,DEFAULT,NON_PRIVATE,NONE,PROTECTED_AND_PUBLIC,PUBLIC_ONLY
属性过滤
在将Java对象序列化为json时,有些属性需要过滤掉,不显示在json中,Jackson有多种实现方法:
1、注解方式,可以用 @JsonIgnore 过滤单个属性或用 @JsonIgnoreProperties 过滤多个属性
@JsonIgnore public int getAge() @JsonIgnoreProperties(value = { "age","birth_date" }) public class Person{...}
!注意: @JsonIgnore会忽略该字段的序列化及反序列化
推荐使用:@JsonProperty(access = Access.WRITE_ONLY)
通过设置JsonProperty的access属性来确定当前属性是不是需要自动序列化/反序列化。
WRITE_ONLY:仅做反序列化操作。
READ_ONLY:仅做序列化操作。
2、addMixIn 方法加注解方式@JsonIgnoreProperties
public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource);
addMixIn 方法的作用是用 mixinSource 接口或类的注解会重写 target 或 target 的子类型的注解
3、SimpleBeanPropertyFilter 方式。这种方式比前两种方式更加灵活,也更复杂一些
1)首先需要设置@JsonFilter 类或接口,
2)其次设置 addMixIn,将@JsonFilter 作用于 java 对象上,
3)最后调用 SimpleBeanPropertyFilter 的 serializeAllExcept 方法或重写 SimpleBeanPropertyFilter 的 serializeAsField 方法来过滤相关属性
//设置 Filter 类或接口 @JsonFilter("myFilter") public interface MyFilter {...} //设置 addMixIn mapper.addMixIn(Person.class, MyFilter.class); //调用 SimpleBeanPropertyFilter 的 serializeAllExcept 方法 SimpleBeanPropertyFilter newFilter = SimpleBeanPropertyFilter.serializeAllExcept("age"); //或重写 SimpleBeanPropertyFilter 的 serializeAsField 方法 SimpleBeanPropertyFilter newFilter = new SimpleBeanPropertyFilter() { @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { if (!writer.getName().equals("age")) { writer.serializeAsField(pojo, jgen, provider); } } }; //设置 FilterProvider FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", newFilter); mapper.setFilterProvider(filterProvider).writeValueAsString(person);
反序列化时,忽略JSON中存在,而Java对象类不存在的属性
1、在需要转化的Java对象类中添加注解
@JsonIgnoreProperties(ignoreUnknown = true)
2、修改MAPPER对象
MAPPER = new ObjectMapper(); // 忽略JSON字符串有的,而反序列化的Java对象没有的属性 MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
自定义序列化和反序列化
自定义的序列化类需要直接或间接继承StdSerializer 或 JsonSerializer,同时需要利用 JsonGenerator 生成 json,重写方法 serialize,如自定义序列化:
public class CustomSerializer extends StdSerializer<Person> { @Override public void serialize(Person person, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); jsonGenerator.writeNumberField("age", person.getAge()); jsonGenerator.writeStringField("name", person.getName()); jsonGenerator.writeEndObject(); } }
定义好自定义序列化类和自定义反序列化类,若想在程序中调用它们,还需要注册到 ObjectMapper 的 Module,示例如下:
SimpleModule module = new SimpleModule("myModule"); module.addSerializer(new CustomSerializer(Person.class)); module.addDeserializer(Person.class,new CustomDeserializer()); // 注册module到mapper mapper.registerModule(module); // 也可通过注解方式加在java对象的属性,方法或类上面来调用它们, @JsonSerialize(using = CustomSerializer.class) @JsonDeserialize(using = CustomDeserializer.class) public class Person{...}
Spring中对某个bean自定义序列化方式:
/** * TimeOfDay 自定义序列化和反序列化 * * @author yangyongjie */ @JsonComponent public class CustomTimeOfDaySerializerAndDeserializer { public static class TimeOfDaySerializer extends JsonSerializer<TimeOfDay> { @Override public void serialize(TimeOfDay timeOfDay, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, timeOfDay.getHour()); cal.set(Calendar.MINUTE, timeOfDay.getMinute()); cal.set(Calendar.SECOND, timeOfDay.getSecond()); jsonGenerator.writeNumber(cal.getTimeInMillis()); } } public static class TimeOfDayDeserializer extends JsonDeserializer<TimeOfDay> { @Override public TimeOfDay deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { return TimeOfDay.hourAndMinuteAndSecondFromDate(deserializationContext.readValue(jsonParser, Date.class)); } } }
工具类:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
/**
* Jackson工具类
*
* @author yangyongjie
*/
public class JacksonUtil {
/**
* ObjectMapper 对象可重复使用
*/
private static final ObjectMapper MAPPER;
static {
MAPPER = new ObjectMapper();
// 忽略JSON字符串有的,而反序列化的Java对象没有的属性
MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUtil.class);
private JacksonUtil() {
}
/**
* 对象转换为jsonString
*
* @param obj
* @return
*/
public static String toString(Object obj) {
return toString(obj, "");
}
/**
* 对象转换为jsonString
*
* @param obj
* @param defaultString
* @return
*/
public static String toString(Object obj, String defaultString) {
try {
return MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
LOGGER.error("writeValueAsString:" + e.getMessage(), e);
}
return defaultString;
}
/**
* 反序列化为对象,不带泛型
*
* @param jsonString
* @param tClass
* @param <T>
* @return
*/
public static <T> T toObject(String jsonString, Class<T> tClass) {
return toObject(jsonString, null, tClass);
}
/**
* 反序列化为对象,不带泛型
*
* @param jsonString
* @param defaultValue
* @param clazz
* @param <T>
* @return
*/
public static <T> T toObject(String jsonString, T defaultValue, Class<T> clazz) {
try {
return MAPPER.readValue(jsonString, clazz);
} catch (Exception e) {
LOGGER.error("readValue:" + e.getMessage(), e);
}
return defaultValue;
}
/**
* 反序列化为对象,带泛型
*
* @param jsonString
* @param typeReference
* @param <T>
* @return
*/
public static <T> T toObject(String jsonString, TypeReference<T> typeReference) {
return toObject(jsonString, null, typeReference);
}
/**
* 反序列化为对象,带泛型
*
* @param jsonString
* @param defaultValue
* @param typeReference
* @return
*/
public static <T> T toObject(String jsonString, T defaultValue, TypeReference<T> typeReference) {
try {
return MAPPER.readValue(jsonString, typeReference);
} catch (Exception e) {
LOGGER.error("readValue:" + e.getMessage(), e);
}
return defaultValue;
}
/**
* Object转成指定对象类型
* @param obj
* @param typeReference
* @param <T>
* @return
*/
public static <T> T obj2Obj(Object obj, TypeReference<T> typeReference) {
try {
return MAPPER.readValue(MAPPER.writeValueAsString(obj), typeReference);
} catch (Exception e) {
LOGGER.error("readValue:" + e.getMessage(), e);
}
return null;
}
/**
* 反序列化对象,返回list
*
* @param jsonString
* @param clazz
* @param <T> List中元素的泛型
* @return
*/
public static <T> List<T> ofList(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
CollectionType javaType = MAPPER.getTypeFactory().constructCollectionType(List.class, clazz);
try {
return MAPPER.readValue(jsonString, javaType);
} catch (JsonProcessingException e) {
LOGGER.error("ofList:" + e.getMessage(), e);
}
return null;
}
/**
* 反序列化为对象,带泛型
*
* @param jsonString
* @param typeReference
* @param <T> 代表List本身的泛型
* @return
*/
public static <T> T ofList(String jsonString, TypeReference<T> typeReference) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return MAPPER.readValue(jsonString, typeReference);
} catch (JsonProcessingException e) {
LOGGER.error("ofList:" + e.getMessage(), e);
}
return null;
}
/**
* 反序列化对象,返回map
*
* @param jsonString
* @param keyClazz
* @param valueClazz
* @param <K>
* @param <V>
* @return
*/
public static <K, V> Map<K, V> ofMap(String jsonString, Class<K> keyClazz, Class<V> valueClazz) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
MapType javaType = MAPPER.getTypeFactory().constructMapType(Map.class, keyClazz, valueClazz);
try {
return MAPPER.readValue(jsonString, javaType);
} catch (JsonProcessingException e) {
LOGGER.error("ofMap:" + e.getMessage(), e);
}
return null;
}
/**
* 将一个对象转为另一个对象
*
* @param object
* @param clazz
* @param <T>
* @return
*/
public static <T> T convert(Object object, Class<T> clazz) {
if (object == null) {
return null;
}
try {
return MAPPER.convertValue(object, clazz);
} catch (Exception e) {
LOGGER.error("convert:" + e.getMessage(), e);
}
return null;
}
}
参考:
https://developer.ibm.com/zh/articles/jackson-advanced-application/
http://tutorials.jenkov.com/java-json/index.html
END.