Обработка исключения "нераспознанный токен" в пользовательском json с 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)
I попробовали зарегистрировать DeserializationProblemHandler
С ObjectMapper
но она никогда не вызывается, когда эта проблема возникает.
вот пример приложения, которое показывает, что я пробовал:
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)
может ли кто-нибудь указать, почему обработчик никогда не вызывается? Или, если есть лучший разбор этого пользовательского документа json (Джексон или нет...), дайте мне знать.
2 ответов
обработчик не вызывается, потому что недопустимая часть не является свойством ("two"
), но значение (nonStandardThing()
).
очевидный способ справиться с этим, - передать nonStandardThing()
как String
, т. е. перепишите документ JSON как
{
"test": {
"one":"oneThing",
"two": "nonStandardThing()",
"three": true
}
}
если это невозможно, то делать особо нечего. С помощью настраиваемого Jackson
Deserializer
имеет смысл только для свойств, а не значения.
содержимое, которое вы перечисляете, к сожалению, недействительно JSON, поэтому то, что у вас есть, на самом деле не является документом JSON, но, возможно, сериализация объекта Javascript. Все строковые значения должны быть заключены в двойные кавычки в JSON.
Джексон не поддерживает чтение такого контента напрямую, но его можно прочитать с помощью парсера YAML, такого как SnakeYAML. Джексон также имеет модуль формата данных YAML в https://github.com/FasterXML/jackson-dataformat-yaml/ Так вы смогли возможно, использовать. Учитывая, что ЯМЛ (в основном!) суперсет JSON, он, вероятно, может делать то, что вы хотите.