Jackson常用配置示例
Jackson 提供了
SerializationFeature
、
DeserializationFeature
来自定义
ObjectMapper
的行为。
对输出缩进
public class MyObject {
private int intVal;
private String stringVal;
private List<String> list;
.............
}
默认配置下的 JSON 输出是没有缩进的:
MyObject myObject = new MyObject(3, "test String",
List.of("one", "two"));
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(myObject);
System.out.println(s);
{"intVal":3,"stringVal":"test String","list":["one","two"]}
可以用 om.enable(..)
、om.configure(.., true)
开启缩进或其他功能:
MyObject myObject = new MyObject(3, "test String",
List.of("one", "two"));
ObjectMapper om = new ObjectMapper();
om.enable(SerializationFeature.INDENT_OUTPUT);
// om.configure(SerializationFeature.INDENT_OUTPUT, true);
String s = om.writeValueAsString(myObject);
System.out.println(s);
{
"intVal" : 3,
"stringVal" : "test String",
"list" : [ "one", "two" ]
}
Fail on Unknown Properties
反序列化时,若遇到未知的属性(没有对应的属性,也没有setter 或 handler来处理这样的属性)会抛出异常,
public class MyObject2 {
private int intVal;
public MyObject2(int intVal) {
this.intVal = intVal;
}
public MyObject2() {
}
...
}
默认会报错:
String jsonSting = "{\"intVal\":3,\"strVal\":\"3\"}";
ObjectMapper om = new ObjectMapper();
System.out.println(jsonSting);
MyObject2 myObject = om.readValue(jsonSting, MyObject2.class);
System.out.println(myObject);
{"intVal":3,"strVal":"3"}
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "strVal" (class org.example.c2.MyObject2), not marked as ignorable (one known property: "intVal"])
at [Source: (String)"{"intVal":3,"strVal":"3"}"; line: 1, column: 23] (through reference chain: org.example.c2.MyObject2["strVal"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:987)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1974)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1701)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1679)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:330)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
at org.example.c2.DisableFailOnUnknownProps.disableFailOnUnknownProps2(DisableFailOnUnknownProps.java:49)
at org.example.c2.DisableFailOnUnknownProps.main(DisableFailOnUnknownProps.java:19)
禁用 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
String jsonSting = "{\"intVal\":3,\"strVal\":\"3\"}";
ObjectMapper om = new ObjectMapper();
om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
System.out.println(jsonSting);
MyObject2 myObject = om.readValue(jsonSting, MyObject2.class);
System.out.println(myObject);
{"intVal":3,"strVal":"3"}
MyObject2{intVal=3}
允许序列化空对象
MyEmptyObject
没有可序列化的属性,Jackson 默认的字段属性发现规则:所有被 public
修饰的字段、所有被 public
修饰的getter。没有可序列化的属性时,会抛出异常。
public class MyEmptyObject {
private int i = 10;
}
默认:
MyEmptyObject myObject = new MyEmptyObject();
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(myObject);
System.out.println(s);
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.example.c2.MyEmptyObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4487)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3742)
at org.example.c2.DisableFailOnEmptyBeans.defaultOutput(DisableFailOnEmptyBeans.java:24)
at org.example.c2.DisableFailOnEmptyBeans.main(DisableFailOnEmptyBeans.java:17)
Process finished with exit code 1
禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS
MyEmptyObject myObject = new MyEmptyObject();
ObjectMapper om = new ObjectMapper();
om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
String s = om.writeValueAsString(myObject);
System.out.println(s);
{}
将空字符串反序列化为 null POJO
默认情况下,空字符串不能反序列化为 null 对象,会抛异常:
String s = "{\"myObjKey\":\"\"}";
System.out.println("input:\n" + s);
ObjectMapper om = new ObjectMapper();
Map<String, MyObject> myObject = om.readValue(s, new TypeReference<Map<String, MyObject>>() { });
System.out.println(myObject);
input:
{"myObjKey":""}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("") to `org.example.c2.MyObject` value (but could if coercion was enabled using `CoercionConfig`)
at [Source: (String)"{"myObjKey":""}"; line: 1, column: 13] (through reference chain: java.util.LinkedHashMap["myObjKey"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadCoercion(DeserializationContext.java:1666)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._checkCoercionFail(StdDeserializer.java:1432)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromEmptyString(StdDeserializer.java:325)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:270)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1495)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:207)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:197)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:609)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:437)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3531)
at org.example.c2.EnableEmptyStringAsNullPojo.defaultOutput(EnableEmptyStringAsNullPojo.java:25)
at org.example.c2.EnableEmptyStringAsNullPojo.main(EnableEmptyStringAsNullPojo.java:17)
Process finished with exit code 1
启用 DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
,此设置只能用于 POJO 或一些结构化的值(比如 java.util.Maps
、java.util.Collection
),但不能用于标量值(scalar values ,比如 boolean 和 number),是否可以强制使用它们取决于 MapperFeature.ALLOW_COERCION_OF_SCALARS
。
String s = "{\"myObjKey\":\"\"}";
System.out.println("input:\n" + s);
ObjectMapper om = new ObjectMapper();
om.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
Map<String, MyObject> myObject = om.readValue(s, new TypeReference<Map<String, MyObject>>() { });
System.out.println(myObject);
input:
{"myObjKey":""}
{myObjKey=null}
空字符串与 Java simple objects
Java simple objects 不受 DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
的控制。
BigDecimal
String s = "{\"myObjKey\":\"\"}";
System.out.println("input:\n " + s);
ObjectMapper om = new ObjectMapper();
Map<String, BigDecimal> myObject = om.readValue(s,
new TypeReference<Map<String, BigDecimal>>() { });
System.out.println(myObject);
input:
{"myObjKey":""}
{myObjKey=null}
String
String s = "{\"myObjKey\":\"\"}";
System.out.println("input:\n " + s);
ObjectMapper om = new ObjectMapper();
Map<String, String> myObject = om.readValue(s,
new TypeReference<Map<String, String>>() { });
System.out.println(myObject);
input:
{"myObjKey":""}
{myObjKey=}
序列化时的时间格式化
默认情况下,时间会以时间戳的形式序列化:
Date date = new Date();
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(Map.of("myDate", date));
System.out.println(s);
{"myDate":1618323884853}
禁用 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
Date date = new Date();
ObjectMapper om = new ObjectMapper();
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
String s = om.writeValueAsString(Map.of("myDate", date));
System.out.println(s);
{"myDate":"2021-04-13T14:24:45.061+00:00"}