我已启用 jackson-datatype-joda,但它无法与 JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS
一起使用。
我已经按如下方式设置了 ObjectMapper:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
jacksonObjectMapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
jacksonObjectMapper.registerModule(new JodaModule());
反序列化时(使用 com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer),我最终遇到错误:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Current token (VALUE_STRING) not numeric, can not use numeric value accessors
at [...]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Current token (VALUE_STRING) not numeric, can not use numeric value accessors
我调试了 LocalDateDeserializer 并发现它期望 VALUE_NUMBER_INT - 而 JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS
使日期具有字符串。
当我关闭该功能时,一切正常。
此功能(或类似功能)是否有可能与 Joda Time 一起使用?
最佳答案
Joda
模块使用 com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer
用于反序列化 org.joda.time.LocalDate
对象。这个类看起来像这样:
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
// [yyyy,mm,dd]
if (jp.isExpectedStartArrayToken()) {
jp.nextToken(); // VALUE_NUMBER_INT
int year = jp.getIntValue();
jp.nextToken(); // VALUE_NUMBER_INT
int month = jp.getIntValue();
jp.nextToken(); // VALUE_NUMBER_INT
int day = jp.getIntValue();
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after LocalDate ints");
}
return new LocalDate(year, month, day);
}
switch (jp.getCurrentToken()) {
case VALUE_NUMBER_INT:
return new LocalDate(jp.getLongValue());
case VALUE_STRING:
String str = jp.getText().trim();
if (str.length() == 0) { // [JACKSON-360]
return null;
}
return parser.parseLocalDate(str);
default:
}
throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Array, String or Number");
}
如您所见,如果 LocalDate
是数组,则此反序列化器需要此数组中的整数。您可以编写自定义反序列化器并扩展此实现。请参见以下示例:
class LocalDateWithStringsDeserializer extends LocalDateDeserializer {
private static final long serialVersionUID = 1L;
@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
JsonProcessingException {
// [yyyy,mm,dd] or ["yyyy","mm","dd"]
if (jp.isExpectedStartArrayToken()) {
return parseArray(jp, ctxt);
}
return super.deserialize(jp, ctxt);
}
private LocalDate parseArray(JsonParser jp, DeserializationContext ctxt)
throws JsonParseException, IOException {
int year = getNextValue(jp);
int month = getNextValue(jp);
int day = getNextValue(jp);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after LocalDate ints");
}
return new LocalDate(year, month, day);
}
private int getNextValue(JsonParser jp) throws IOException, JsonParseException {
jp.nextToken();
return new Integer(jp.getText());
}
}
现在您可以链接上面的反序列化器和您的属性:
@JsonDeserialize(using = LocalDateWithStringsDeserializer.class)
private LocalDate date;
关于java - 如何从 JSON 反序列化为 LocalDate,同时还使用 JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24432828/