Пользовательский сериализатор для JsonAnyGetter - PullRequest
0 голосов
/ 15 апреля 2020

Можно ли настроить сопоставитель, используемый при сериализации для JsonAnyGetter (через @JsonSerialize)? У меня есть сценарий использования, в котором у нас есть карта, в которой значением может быть значение Instant: я хотел бы переопределить преобразователь сериализации, чтобы заставить объект Instant сериализоваться в виде строки UT C.

Хотя это можно было бы сделать, переопределив функции сериализации objectMapper, я ищу альтернативный подход: применяя его на уровне нестандартного сериализатора, я могу по существу форсировать эту стратегию сериализации независимо от конфигураций objectMapper любого приложения. (тем самым не требуется, чтобы все приложения меняли свои конфиги objectMapper по причинам совместимости). Обратите внимание, что ExampleMessage представляет базовый класс сообщений, который может использоваться несколькими службами общим способом.

Некоторые примеры кода структуры сообщения:

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class ExampleMessage {

    private final String notificationType;
    private final Map<String, Object> context;

    @JsonCreator
    public ExampleMessage(@JsonProperty("notificationType") String notificationType) {
        this.notificationType = notificationType;
        this.context = new HashMap<>();
    }

    public String getNotificationType() {
        return notificationType;
    }

    @JsonAnyGetter
    public Map<String, Object> getContext() {
        return context;
    }

    @JsonAnySetter
    public void setContext(String key, Object value) {
        this.context.put(key, value);
    }



    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ExampleMessage that = (ExampleMessage) o;
        return Objects.equals(notificationType, that.notificationType) &&
                Objects.equals(context, that.context);
    }

    @Override
    public int hashCode() {
        return Objects.hash(notificationType, context);
    }
}

И неудачный тест:

import com.circle.utils.JsonUtils;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class ExampleMessageTest {

    @Test
    public void shouldSerializeToExpectedJsonString() throws Exception {
        CustomMessage originalMessage = new CustomMessage("some_type");
        originalMessage.setField1("value1");
        SomeObject someObject = new SomeObject();
        someObject.setStringValue("this is a string");
        Map<String, Object> map = new HashMap<>();
        map.put("keyString", "value");
        map.put("keyInt", 123);
        map.put("keyInstant", Instant.parse("2020-01-03T14:00:00.000Z"));
        someObject.setMapValue(map);
        originalMessage.setObject(someObject);

        String json = JsonUtils.toJson(originalMessage);
        JSONAssert.assertEquals("{" +
                "   \"notificationType\":\"some_type\"," +
                "   \"field1\":\"value1\"," +
                "   \"object\":{" +
                "       \"stringValue\":\"this is a string\"," +
                "       \"mapValue\":{" +
                "           \"keyInstant\":\"2020-01-03T14:00:00.000Z\"," +
                "           \"keyString\":\"value\"," +
                "           \"keyInt\":123" +
                "       }" +
                "   }" +
                "}", json, false);
    }

    static class SomeObject {
        private String stringValue;
        private Map<String, Object> mapValue;

        public String getStringValue() {
            return stringValue;
        }

        public void setStringValue(String stringValue) {
            this.stringValue = stringValue;
        }

        public Map<String, Object> getMapValue() {
            return mapValue;
        }

        public void setMapValue(Map<String, Object> mapValue) {
            this.mapValue = mapValue;
        }
    }

    static class CustomMessage extends ExampleMessage {


        private String field1;

        private SomeObject object;

        @JsonCreator
        protected CustomMessage( @JsonProperty("notificationType") String notificationType) {
            super(notificationType);
        }

        public SomeObject getObject() {
            return object;
        }

        public void setObject(SomeObject object) {
            this.object = object;
        }

        public String getField1() {
            return field1;
        }

        public void setField1(String field1) {
            this.field1 = field1;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            CustomMessage that = (CustomMessage) o;
            return Objects.equals(field1, that.field1);
        }

        @Override
        public int hashCode() {
            return Objects.hash(field1);
        }
    }

}

Ошибка подтверждения, которую я получаю:

java.lang.AssertionError: object.mapValue.keyInstant
Expected: 2020-01-03T14:00:00.000Z
     got: 1578060000000

(Мы используем Джексон 2.9).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...