使用 Jackson 处理自定义 json 中的 "Unrecognized token" 异常
Handling "Unrecognized token" exception in custom json with Jackson
我正在尝试使用 Jackson json 解析器 (v2.5.2) 来解析自定义 json 文档,但该文档不真实 json,我无法理解了解如何使其工作。我有一个 json 文档,它可能看起来像:
{
"test": {
"one":"oneThing",
"two": nonStandardThing(),
"three": true
}
}
我想使用 ObjectMapper 将其映射到 java.util.Map
,我只想将 nonStandardThing()
作为字符串值添加到我的映射中,用于键 two
.
当我 运行 通过 ObjectMapper.readValue(json, Map.class)
我得到异常:
com.fasterxml.jackson.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.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
我曾尝试用 ObjectMapper
注册一个 DeserializationProblemHandler
,但在出现此问题时从未调用它。
这是显示我尝试过的示例应用程序:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class JacksonDeserializerTest {
private Logger log = Logger.getLogger(JacksonDeserializerTest.class.getName());
public JacksonDeserializerTest() {
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) {
JacksonDeserializerTest test = new JacksonDeserializerTest();
}
}
输出如下:
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
INFO: Valid json looks like: {test={test1=one, test2=two}}
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
SEVERE: Error parsing json
com.fasterxml.jackson.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.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2129)
谁能指出为什么 Handler 永远不会被调用?或者,如果有更好的解析此自定义 json 文档(jackson 与否...),请告诉我。
处理程序未被调用,因为无效部分不是 属性 ("two"
) 而是值 (nonStandardThing()
).
处理这个问题的一个明显方法是将 nonStandardThing()
作为 String
传递,即将 JSON 文档重写为
{
"test": {
"one":"oneThing",
"two": "nonStandardThing()",
"three": true
}
}
如果那不可能,那就没什么可做的了。使用自定义 Jackson
Deserializer
仅对属性有用,对值没有用。
很遗憾,您列出的内容无效 JSON,因此您所拥有的并不是真正的 JSON 文档,而可能是 Javascript 对象的序列化。
在 JSON.
中,所有字符串值都必须用双引号引起来
Jackson 不支持直接读取此类内容,但可以使用 SnakeYAML 等 YAML 解析器读取此内容。
Jackson 在 https://github.com/FasterXML/jackson-dataformat-yaml/ 也有 YAML 数据格式模块,所以你也许可以使用它。鉴于 YAML(大部分!)是 JSON 的超集,它可能可以做你想做的事。
我正在尝试使用 Jackson json 解析器 (v2.5.2) 来解析自定义 json 文档,但该文档不真实 json,我无法理解了解如何使其工作。我有一个 json 文档,它可能看起来像:
{
"test": {
"one":"oneThing",
"two": nonStandardThing(),
"three": true
}
}
我想使用 ObjectMapper 将其映射到 java.util.Map
,我只想将 nonStandardThing()
作为字符串值添加到我的映射中,用于键 two
.
当我 运行 通过 ObjectMapper.readValue(json, Map.class)
我得到异常:
com.fasterxml.jackson.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.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
我曾尝试用 ObjectMapper
注册一个 DeserializationProblemHandler
,但在出现此问题时从未调用它。
这是显示我尝试过的示例应用程序:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class JacksonDeserializerTest {
private Logger log = Logger.getLogger(JacksonDeserializerTest.class.getName());
public JacksonDeserializerTest() {
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) {
JacksonDeserializerTest test = new JacksonDeserializerTest();
}
}
输出如下:
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
INFO: Valid json looks like: {test={test1=one, test2=two}}
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
SEVERE: Error parsing json
com.fasterxml.jackson.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.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2129)
谁能指出为什么 Handler 永远不会被调用?或者,如果有更好的解析此自定义 json 文档(jackson 与否...),请告诉我。
处理程序未被调用,因为无效部分不是 属性 ("two"
) 而是值 (nonStandardThing()
).
处理这个问题的一个明显方法是将 nonStandardThing()
作为 String
传递,即将 JSON 文档重写为
{
"test": {
"one":"oneThing",
"two": "nonStandardThing()",
"three": true
}
}
如果那不可能,那就没什么可做的了。使用自定义 Jackson
Deserializer
仅对属性有用,对值没有用。
很遗憾,您列出的内容无效 JSON,因此您所拥有的并不是真正的 JSON 文档,而可能是 Javascript 对象的序列化。 在 JSON.
中,所有字符串值都必须用双引号引起来Jackson 不支持直接读取此类内容,但可以使用 SnakeYAML 等 YAML 解析器读取此内容。 Jackson 在 https://github.com/FasterXML/jackson-dataformat-yaml/ 也有 YAML 数据格式模块,所以你也许可以使用它。鉴于 YAML(大部分!)是 JSON 的超集,它可能可以做你想做的事。