jackson-databind
jackson-databind copied to clipboard
getOutputContext().getCurrentName() Persists the previous property name when called on @ JsonAnyGetter
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?