Java 使用 Jackson 处理自定义 json 中的“无法识别的令牌”异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29856116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:42:19  来源:igfitidea点击:

Handling "Unrecognized token" exception in custom json with Hymanson

javajsondata-bindingHymanson

提问by Andrew Serff

I'm trying to use the Hymanson json parser(v2.5.2) to parse a custom json document that isn't true json and I can't figure out how to make it work. I have a json document that might look like:

我正在尝试使用 Hymanson json 解析器(v2.5.2)来解析一个不是真正的 json 的自定义 json 文档,我不知道如何使它工作。我有一个 json 文档,可能如下所示:

{
    "test": {
        "one":"oneThing",
        "two": nonStandardThing(),
        "three": true
    }
}

I want to use the ObjectMapper to map this to a java.util.Mapand I would just like the nonStandardThing()to be added as a String value in my map for the key two.

我想使用 ObjectMapper 将其映射到 a java.util.Map,我只想nonStandardThing()将 的作为 String 值添加到我的映射中的 key two

When I run this through the ObjectMapper.readValue(json, Map.class)I get the exception:

当我运行它时,ObjectMapper.readValue(json, Map.class)我得到了异常:

com.fasterxml.Hymanson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN
 at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35]
    at com.fasterxml.Hymanson.core.JsonParser._constructError(JsonParser.java:1487)
    at com.fasterxml.Hymanson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
    at com.fasterxml.Hymanson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
    at com.fasterxml.Hymanson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)

I have tried to register a DeserializationProblemHandlerwith the ObjectMapperbut it is never called when this problem occurs.

我曾尝试向 注册DeserializationProblemHandlerObjectMapper但在发生此问题时从未调用过。

Here is sample application that shows what I have tried:

这是显示我尝试过的示例应用程序:

import com.fasterxml.Hymanson.core.JsonParser;
import com.fasterxml.Hymanson.core.JsonProcessingException;
import com.fasterxml.Hymanson.databind.DeserializationContext;
import com.fasterxml.Hymanson.databind.JsonDeserializer;
import com.fasterxml.Hymanson.databind.ObjectMapper;
import com.fasterxml.Hymanson.databind.deser.DeserializationProblemHandler;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HymansonDeserializerTest {
    private Logger log = Logger.getLogger(HymansonDeserializerTest.class.getName());
    public HymansonDeserializerTest() {
        String validJson = "{ \"test\":{\"test1\":\"one\",\"test2\":\"two\"}}";
        String invalidJson = "{ \"test\":{\"test1\":nonStandardThing(),\"test2\":\"two\"}}";

        ObjectMapper mapper = new ObjectMapper();
        mapper.addHandler(new DeserializationProblemHandler() {
            @Override
            public boolean handleUnknownProperty(DeserializationContext dc, JsonParser jp, JsonDeserializer<?> jd, Object bean, String property) throws IOException, JsonProcessingException {
                System.out.println("Handling unknown property: " + property);
                return false;
            }
        });

        try {
            log.log(Level.INFO, "Valid json looks like: {0}", mapper.readValue( validJson, Map.class).toString());
            log.log(Level.INFO, "Invalid json looks like: {0}", mapper.readValue(invalidJson, Map.class).toString());
        } catch (IOException ex) {
            log.log(Level.SEVERE, "Error parsing json", ex);
        }

    }

    public static void main(String[] args) {
        HymansonDeserializerTest test = new HymansonDeserializerTest();
    }
}

The output looks like:

输出看起来像:

Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.Hymanson.HymansonDeserializerTest <init>
INFO: Valid json looks like: {test={test1=one, test2=two}}
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.Hymanson.HymansonDeserializerTest <init>
SEVERE: Error parsing json
com.fasterxml.Hymanson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN
 at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35]
    at com.fasterxml.Hymanson.core.JsonParser._constructError(JsonParser.java:1487)
    at com.fasterxml.Hymanson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
    at com.fasterxml.Hymanson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
    at com.fasterxml.Hymanson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
    at com.fasterxml.Hymanson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2129)

Can anyone point out why the Handler never gets called? Or, if there is a better parse this custom json document (Hymanson or not...), let me know.

谁能指出为什么 Handler 永远不会被调用?或者,如果有更好的解析这个自定义 json 文档(Hyman逊与否...),请告诉我。

采纳答案by PNS

The handler is not called because the invalid part is not the property ("two") but the value (nonStandardThing()).

不会调用处理程序,因为无效部分不是属性 ( "two") 而是值 ( nonStandardThing())。

An obvious way to handle this, is to pass nonStandardThing()as a String, i.e. rewrite the JSON document as

处理这个问题的一个显而易见的方法是nonStandardThing()作为 a传递,即将StringJSON 文档重写为

{
    "test": {
        "one":"oneThing",
        "two": "nonStandardThing()",
        "three": true
    }
}

If that is not a possibility, there is not much to do. Using a custom HymansonDeserializeris only useful for properties, not values.

如果这不可能,那就没什么可做的了。使用自定义HymansonDeserializer仅对属性有用,而不对值有用。

回答by StaxMan

Content you list is unfortunately not valid JSON, so what you have is not really a JSON document, but perhaps serialization of a Javascript object. All String values MUST be enclosed in double quotes in JSON.

不幸的是,您列出的内容不是有效的 JSON,因此您所拥有的并不是真正的 JSON 文档,而是 Javascript 对象的序列化。在 JSON 中,所有字符串值都必须用双引号括起来。

Hymanson does not support reading of such content directly, but it may be possible to read this using YAML parser like SnakeYAML. Hymanson also has YAML data format module at https://github.com/FasterXML/Hymanson-dataformat-yaml/so you could perhaps use that. Given that YAML is (mostly!) a superset of JSON, it could probably do what you want.

Hymanson 不支持直接读取此类内容,但可以使用 YAML 解析器(如 SnakeYAML)读取这些内容。Hymanson 在https://github.com/FasterXML/Hymanson-dataformat-yaml/也有 YAML 数据格式模块,所以你也许可以使用它。鉴于 YAML 是(主要是!)JSON 的超集,它可能可以满足您的需求。