Джексон - разрешить ведущие нули и оставить их

У меня есть следующий компонент Java:

public class Something {

    @NotBlank
    private final String value;

    @JsonCreator
    public Something(@JsonProperty("value")final String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(final Object o) {
        return EqualsBuilder.reflectionEquals(this, o);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }
}

И следующий служебный класс для обработки json-сериализации и десериализации

public class JsonUtils {

    private final ObjectMapper objectMapper;

    @Inject
    public JsonUtils(final ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public <T> T jsonToObject(final String jsonString, final Class<T> classType) {

        try {
            return objectMapper.readValue(jsonString, classType);
        } catch (IOException e) {
            throw new JsonException(ErrorMessage.ERROR_PARSE_JSON_TO_OBJECT, e);
        }
    }

    public <V> String objectToJson(final V objectToBeParsed) {

        try {
            return objectMapper.writeValueAsString(objectToBeParsed);
        } catch (IOException e) {
            throw new JsonException(ErrorMessage.ERROR_PARSE_OBJECT_TO_JSON, e);
        }
    }
}

Здесь настраивается мой сопоставитель объектов

public class ParserModule extends AbstractModule {

    @Provides
    public ObjectMapper getObjectMapper() {

        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.enable(ALLOW_NUMERIC_LEADING_ZEROS);

        objectMapper.findAndRegisterModules();
        objectMapper.registerModule(getSerializersModule());
        objectMapper.registerModule(getDeserializerModule());

        return objectMapper;
    }

    private SimpleModule getSerializersModule() {

        final SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Something.class, new SomethingSerializer());

        return simpleModule;
    }

    private SimpleModule getDeserializerModule() {

        final SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Something.class, new SomethingDeserializer());

        return simpleModule;
    }
}

Этот объект JSON в конце будет возвращенным значением в теле ответа REST API, но спецификация API ожидает необработанную строку, содержащую только значение поля «значение». Итак, если my Something имеет значение "hello world", он должен возвращать hello world в теле ответа, а не {"value":"hello world"}.

Эта спецификация не была определена мной, я должен ее соблюдать, и она не может измениться.

Итак, я создал следующий сериализатор и десериализатор, которые зарегистрированы в сопоставлении объектов, как было показано ранее.

public class SomethingSerializer extends StdSerializer<Something> {

    public SomethingSerializer() {
        this(null);
    }

    public SomethingSerializer(final Class<Something> t) {
        super(t);
    }

    @Override
    public void serialize(final Something something, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeRawValue(something.getValue());
    }
}

public class SomethingDeserializer extends StdDeserializer<Something> {

    public SomethingDeserializer() {
        this(null);
    }

    public SomethingDeserializer(final Class<?> t) {
        super(t);
    }

    @Override
    public Something deserialize(final JsonParser jsonParser, final DeserializationContext context) throws IOException {
        return new Something(jsonParser.getCodec().readTree(jsonParser).toString());
    }
}

Теперь фактическое значение, которое у меня есть в моем объекте something, не "hello world", а скорее строка, которая выглядит так: 01.something.this.that.org. Обратите внимание на начальный ноль здесь.

Итак, всякий раз, когда я пытаюсь десериализовать такой объект:

Something result = jsonUtils.jsonToObject(response.getBody(), Something.class);

У меня исключение:

JsonParseException: Invalid numeric value: Leading zeroes not allowed
 at [Source: (String)"01.something.this.that.org"; line: 1, column: 2]

Изучив это исключение в источнике Джексона, я обнаружил, что есть функция, которая позволяет мне «пропустить» это исключение, и я подумал, что нашел свое решение, поэтому я добавил это в свой сопоставитель объектов:

objectMapper.enable(ALLOW_NUMERIC_LEADING_ZEROS);

И теперь я больше не получаю исключения, круто. Но десериализованная строка становится: 1.something.this.that.org. Итак, я вернулся к исходной точке.

Есть ли способ:
1) не получить исключение по ведущим нулям
2) фактически сохраните ведущие нули

Спасибо.

Редактировать:

На самом деле, после добавления функции, разрешающей начальные нули, мой первый тест состоял в том, чтобы проанализировать только значение 01, которое вернуло 1, но если я попытаюсь проанализировать образец строки, которую я дал здесь, я получаю другое исключение:

JsonParseException: Unexpected character ('s') in numeric value: Decimal point not followed by a digit at [Source: (String)"01.something.this.that.org"; line: 1, column: 5]

Итак, я предполагаю, что мой вопрос действительно в том, как я могу заставить Джексона интерпретировать необработанную строку как фактическую строку, поскольку прямо сейчас он, кажется, интерпретирует ее как число.

Очень странно! Почему вы заставляете Джексона сериализовать и десериализовать то, что не является JSON?

forty-two 17.12.2018 18:42

в некоторых случаях (например, в случае ошибок) API будет возвращать фактические правильные строки json, иначе я бы действительно просто рассматривал его как простой текст

Verv 17.12.2018 18:55
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
2 222
0

Другие вопросы по теме