Сериализация Джексона класса с помощью Generi c Свойство теряет информацию о типе свойства generi c - PullRequest
1 голос
/ 04 апреля 2020

У меня возникают трудности с получением информации о типе для свойства generi c, которое необходимо сохранить, когда я использую объект Jackson objectMapper для сериализации полезной нагрузки в строковое значение.

Ниже приведен результат, которого я хотел бы достичь .

{"@type":"BlockChainWrapper","@id":1,"payload":{"@type":"TestClassA","@id":2,"helloWorld":"Hello World"},"nonce":255,"signature":"SGVsbG8gV29ybGQ="}

На самом деле я получаю следующий результат (отмечая отсутствующую информацию @type для TestClassA.

{"@type":"BlockChainWrapper","@id":1,"payload":{"@id":2,"helloWorld":"Hello World"},"nonce":255,"signature":"SGVsbG8gV29ybGQ="}

Используемый мной тест:

class BlockChainWrapperTest extends Specification {

    def objectMapper = JacksonConfiguration.createObjectMapper()

    def "test Json marshalling"() {
        given: "A test payload"
        def payload = new BlockChainWrapper<TestClassA>(
                payload: new TestClassA(),
                nonce: 255,
                signature: "Hello World".getBytes(Charset.defaultCharset())
        )

        when:
        //ObjectWriter w = objectMapper.writerFor(new TypeReference<BlockChainWrapper<TestClassA>>() { });
        //def result = w.writeValueAsString(payload)
        def result = objectMapper.writeValueAsString(payload)

        then:
        assert result == "{\"@type\":\"BlockChainWrapper\",\"@id\":1,\"payload\":{\"@type\":\"TestClassA\",\"@id\":2,\"helloWorld\":\"Hello World\"},\"nonce\":255,\"signature\":\"SGVsbG8gV29ybGQ=\"}"
    }

    def "test TestClassA generates correct JSON"() {
        given:
        def payload = new TestClassA()

        when:
        def result = objectMapper.writeValueAsString(payload)

        then:
        assert result == "{\"@type\":\"TestClassA\",\"@id\":1,\"helloWorld\":\"Hello World\"}"
    }
}

В тесте "test JSON Marshalling" есть две версии. И закомментированная версия, и некомментированная версия дают абсолютно одинаковые результаты.

Второй тест подтверждает, что TestClassA генерирует правильный введите информацию сами по себе.

Проблема становится проблемой только тогда, когда включается родительский класс с типом Generi c, что приводит к потере информации о типе и вызывает десериализацию для возврата LinkedHashMap для содержимого Вместо TestClassA.

TestClassA выглядит следующим образом:

@JsonRootName("TestClassA")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class TestClassA implements Serializable {

    private String helloWorld = "Hello World";
}

Универсальный класс c ks like:

@JsonRootName("BlockChainWrapper")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class BlockChainWrapper<T> implements Serializable {

    private T payload;

Для полноты конфигурации Jackson ObjectMapper:

var mapper = new Jackson2ObjectMapperBuilder()
    .createXmlMapper(false)
    .modules(new JavaTimeModule(), new Jdk8Module())
    .serializationInclusion(JsonInclude.Include.NON_NULL)
    .build();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

1 Ответ

1 голос
/ 04 апреля 2020

Я думаю, я исправил вашу проблему. Я создал проект GitHub с решением. https://github.com/GaetanoPiazzolla/stackoverflow-question-61025761

Короче говоря, вы должны поместить аннотацию @ JsonTypeInfo также в поле Полезная нагрузка :

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@type")
private T payload;
...