简体   繁体   中英

Override jackson @JsonValue from superclass

I have an interface (that already contains a Jackson annotation):

interface Interface {
    @JsonValue
    String fieldA();

    String fieldB();
}

which I cannot modify, and a class that implements this interface:

class Impl implements Interface {
    String fieldA;
    String fieldB;

    public Impl(String fieldA, String fieldB) {
        this.fieldA = fieldA;
        this.fieldB = fieldB;
    }

    @Override
    @JsonSerialize
    public String fieldA() {
        return fieldA;
    }

    @Override
    @JsonSerialize
    public String fieldB() {
        return fieldB;
    }
}

Now, when I serialize the Impl class I would expect that the generated Json would have both fields ( fieldA and fieldB ) present.

This is not the case:

@Test
void should_serialize_both_fields() throws JsonProcessingException {
    // Given
    ObjectMapper mapper = new ObjectMapper();
    Impl example = new Impl("test", "test");
    String expected = "{\"fieldA\": \"test\", \"fieldB\": \"test\"}";

    // When
    String json = mapper.writeValueAsString(example);

    // Then
    org.assertj.core.api.Assertions.assertThat(json).isEqualTo(expected);
}

In this test the resulting json is "test" instead of {"fieldA": "test", "fieldB": "test"} :

org.opentest4j.AssertionFailedError: 
Expecting:
 <""test"">
to be equal to:
 <"{"fieldA": "test", "fieldB": "test"}">
but was not.

The problem comes from the already present @JsonValue annotation on the interface, which I cannot modify. Also, if I try to annotate another method in Impl then I get this exception from jackson:

com.fasterxml.jackson.databind.JsonMappingException: Problem with definition of [AnnotedClass com.actility.m2m.commons.service.error.InternalErrorCodeImplTest$Impl]: Multiple 'as-value' properties defined ([method com.actility.m2m.commons.service.error.InternalErrorCodeImplTest$Impl#fieldB(0 params)] vs [method com.actility.m2m.commons.service.error.InternalErrorCodeImplTest$Impl#fieldA(0 params)])

Is there any way to achieve this?

Going by the docs , you should be able to set a "false" JSON value in the subclass:

Boolean argument is only used so that sub-classes can "disable" annotation if necessary.

I guess that already tells you all you need to know, but here's what it would look like:

class Impl implements Interface {
    //...

    @Override
    @JsonSerialize
    @JsonValue(false) //...disables inherited annotation
    public String fieldA() {
        return fieldA;
    }

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM