jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

getOutputContext().getCurrentName() Persists the previous property name when called on @ JsonAnyGetter

Open Aravinda93 opened this issue 2 years ago • 0 comments

I was asked to file this issue against Jackson-Databind based on the discussion on the Google-Forum.

Basically, the problem is that when Jackson Custom Serializer is called against 2 fields 1. (Field1) Normal field 2. (Field2) annotated with @JsonAnyGetter then on the 2nd call (Field2 call) we get the field name of the 1st within the Custom Searlizer for gen.getOutputContext().getCurrentName().

I believe on the 2nd call (Field2 call) either we should get Empty String or we should get the name of the field (Field2).

The following code samples provide more clarity on this issue:

Customer POJO class used for serializing the JSON:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@NoArgsConstructor
public class Customer {
    private String isA;
    private String name;

    @JsonSerialize(using = CustomSerializer.class)
    private Map<String, Object> extensions = new HashMap<>();

    private Map<String, Object> withoutExtensions = new HashMap<>();

    @JsonAnyGetter
    @JsonSerialize(using = CustomSerializer.class)
    public Map<String, Object> getWithoutExtensions() {
        return withoutExtensions;
    }

}

Following is my CustomSerializer which will be called by 2 fields (extensions and withoutExtensions) during the creation of JSON:

public class CustomSerializer extends JsonSerializer<Map<String, Object>> {

    @Override
    public void serialize(Map<String, Object> value, JsonGenerator gen, SerializerProvider serializers) {

         System.out.println(gen.getOutputContext().getCurrentName());

        //In my case for both "Extensions" and "WithoutExtensions" i get the "currentName" as "Extensions"
    }
}

Following is my Main class which will create a JSON:

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        final Customer customer = new Customer();

        customer.setName("Jackson");

        Map<String, Object> extensions = new HashMap<>();
        extensions.put("WithObject", "With");
        customer.setExtensions(extensions);

        Map<String, Object> withoutExtensions = new HashMap<>();
        extensions.put("WithoutObject", "Without");
        customer.setWithoutExtensions(withoutExtensions);

        final String eventAsJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
        System.out.println(eventAsJson);
    }
}

As we can see when I run the application the CustomSerializer would print extensions in both cases. I believe it should print extensions only once and in the next case either it should provide withoutExtensions or empty string.

Can some expert here confirm if this is bug on the Jackson side?

Aravinda93 avatar Jul 12 '21 03:07 Aravinda93