Fasterxml ObjectMapper:日期解析 - 意外字符(' - '(代码45))

时间:2015-09-12 22:13:33

标签: java json fasterxml

JSON:

{name:"abc",TxnDateUTC:2015-09-07T21:11:19Z}

Java代码:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.readValue( jsonString, Message.class );

例外:

Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('-' (code 45)): was expecting comma to separate OBJECT entries
at [Source: java.io.StringReader@1aa7ecca; line: 1, column: 113]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1378)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:599)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:520)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:599)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:301)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)

据我所知,由于日期值不加引号,因此objectMapper会抛出异常,因为它不知道如何解析不带引号的值。但由于我无法控制json格式,我该如何解析这个json?

当我在json字符串中引用日期值时,相同的代码工作正常。

1 个答案:

答案 0 :(得分:2)

你应该阅读这个,你的问题几乎完全相同(阅读接受的答案):

ALLOW_UNQUOTED_FIELD_NAMES in jackon JSON library

因此,简而言之,allowUnquoted的行为相当不规律,在这种情况下, - 字符会将其抛弃。所以,你的json应该来自:

{name:"abc",TxnDateUTC:2015-09-07T21:11:19Z}

到此:

{name:"abc",TxnDateUTC:"2015-09-07T21:11:19Z"}

更严格的是,它应该是:

{"name":"abc","TxnDateUTC":"2015-09-07T21:11:19Z"}

修改:此外,如果您希望我们帮助您,您将来发布消息代码。既然你对json没有影响(这不是),你可以写一个自定义解析器

Editx2 :由于我是一个好人,我也为你实现了一个(相当容易出错的)自定义解析器,尽管你贬低了我的答案。您只需注释您的Message类:

@JsonDeserialize(using = MessageDeserializer.class)
public class Message {

并且有一个像这样的反序列化器(我假设你可以将一个String转换为DateTime或者你正在使用的任何日期,如果你不喜欢这个名字和Txblabla都是字符串的事实,并且如果模式不是不匹配所以这里不包括这样的代码):

public class MessageDeserializer extends JsonDeserializer<Message> {
    private final Pattern NAME_PATTERN = Pattern.compile(".*?(\"?)name(\"?)[\\s]*:[\\s]*(\".*\").*?");
    private final Pattern DATE_PATTERN = Pattern.compile(".*?TxnDateUTC:\"?([A-Za-z0-9\\-:]{20}).*?");

    @Override
    public Message deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        JsonLocation currentLocation = jp.getCurrentLocation();
        String jsonString = (String) currentLocation.getSourceRef();
        Matcher nameMatcher = NAME_PATTERN.matcher(jsonString);
        String name = "";
        if ( nameMatcher.matches() && nameMatcher.groupCount() == 3 ){
            name = nameMatcher.group(3);
        }

        Matcher dateMatcher = DATE_PATTERN.matcher(jsonString);
        String date = "";
        if ( dateMatcher.matches() && dateMatcher.groupCount() == 1 ){
            date = dateMatcher.group(1);
        }
        return new Message(name, date);
    }
}