Обработка исключений "Неопознанный токен" в пользовательском json с Jackson

Я пытаюсь использовать парсер Jackson json (v2.5.2) для анализа пользовательского json-документа, который не является истинным json, и я не могу понять, как заставить его работать. У меня есть json-документ, который может выглядеть так:

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

Я хочу использовать ObjectMapper для сопоставления этого с java.util.Map, и мне бы хотелось, чтобы nonStandardThing() добавлялся как значение String на моей карте для ключа 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)

Я попытался зарегистрировать 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)

Может ли кто-нибудь указать, почему Handler никогда не вызван? Или, если есть лучший анализ этого пользовательского json-документа (джексон или нет...), дайте мне знать.

Ответ 1

Обработчик не вызывается, потому что недопустимая часть не является свойством ("two"), а значением (nonStandardThing()).

Очевидный способ справиться с этим - передать nonStandardThing() как String, то есть переписать документ JSON как

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

Если это не возможно, делать нечего. Использование пользовательского Jackson Deserializer полезно только для свойств, а не для значений.

Ответ 2

Содержание, к которому вы, к сожалению, не относится к JSON, так что у вас на самом деле не JSON-документ, а, возможно, сериализация объекта Javascript. Все значения String ДОЛЖНЫ быть заключены в двойные кавычки в JSON.

Джексон не поддерживает прямое чтение такого контента, но его можно прочитать с помощью парсера YAML, такого как SnakeYAML. У Jackson также есть модуль формата данных YAML в https://github.com/FasterXML/jackson-dataformat-yaml/, чтобы вы могли его использовать. Учитывая, что YAML (в основном!) Является надмножеством JSON, он, вероятно, может делать то, что вы хотите.

Ответ 3

Я пытаюсь выполнить вызов Post Rest для веб-службы API, но получаю нераспознанный токен, когда пытаюсь отправить сведения в веб-службу.

API веб-службы имеет вид @http:///takeParams? DeviceId = 12345 & cpName = Metropolitan + Plant & personNo = 20335 & fullName = Adams% 2C + Eliza & punchTS = 2019-10-12T13% 3A57% 3A47.149721045 & pcName = LMP-казино

И ошибка, которую я получаю, заключается в следующем

com.fasterxml.jackson.core.JsonParseException: нераспознанный токен "Метрополитен": ожидал ("истина", "ложь" или "ноль") в [Source: (String) " Столичный завод Эмплеадо: Адамс, Элиза (20335) Феча: 2019-10-12T20: 57: 35.446584274 LMP-Casino Desayuno "; строка: 2, столбец: 13] :: ошибка при разборе ответа

Можете пожалуйста кто-нибудь советовать?