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

Yat*_*oel 4 java json fasterxml

杰森:

{name:"abc",TxnDateUTC:2015-09-07T21:11:19Z}
Run Code Online (Sandbox Code Playgroud)

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 );
Run Code Online (Sandbox Code Playgroud)

例外:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

Nik*_*hev 7

您也许应该阅读此内容,您的问题几乎与以下内容完全相同(阅读已接受的答案):

jackon JSON 库中的 ALLOW_UNQUOTED_FIELD_NAMES

因此,简而言之,allowUnquoted 的行为相当不稳定,在这种情况下 - 字符确实会使其失效。所以,你的 json 应该变成这样:

{name:"abc",TxnDateUTC:2015-09-07T21:11:19Z}
Run Code Online (Sandbox Code Playgroud)

对此:

{name:"abc",TxnDateUTC:"2015-09-07T21:11:19Z"}
Run Code Online (Sandbox Code Playgroud)

更严格地说,应该是:

{"name":"abc","TxnDateUTC":"2015-09-07T21:11:19Z"}
Run Code Online (Sandbox Code Playgroud)

编辑:此外,将来,如果您希望我们为您提供帮助,您应该发布您的消息代码。由于您对 json 没有影响(这不是),您可以编写一个自定义解析器

Editx2:因为我是一个好人,所以我还为你实现了一个(相当容易出错的)自定义解析器,尽管你对我的答案投了反对票。您只需像这样注释您的 Message 类:

@JsonDeserialize(using = MessageDeserializer.class)
public class Message {
Run Code Online (Sandbox Code Playgroud)

并有一个像这样的反序列化器(我假设您可以将字符串转换为日期时间或您正在使用的任何日期,如果您不喜欢 name 和 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);
    }
}
Run Code Online (Sandbox Code Playgroud)