0

Having the class:

public class MyClass {
    private String id;
    private Map<String, Object> properties;
    ...
}

and using Jackson, can I tell Jackson (via annotation) to serialize the key values in the properties map to top level key values in the MyClass serialization?

For example, if properties contains a couple of key-values: fruit - apple, color - red I would like to generate a JSON that looks like this:

{
    "if": "...",
    "fruit": "apple",
    "color": "red"
}

instead of:

{
    "if": "...",
    "properties": {
        "fruit": "apple",
        "color": "red"
    }
}
Gabriel Petrovay
  • 20,476
  • 22
  • 97
  • 168
  • 1
    Try to annotate getter method with `@JsonAnyGetter` annotation. Take a look on similar questions: [Adding a dynamic json property as java pojo for jackson](https://stackoverflow.com/questions/56245719/adding-a-dynamic-json-property-as-java-pojo-for-jackson/56247021#56247021), [How to use dynamic property names for a Json object](https://stackoverflow.com/questions/55684724/how-to-use-dynamic-property-names-for-a-json-object/55687330#55687330) – Michał Ziober Sep 19 '21 at 19:47

2 Answers2

0

How can I serialize the key values pairs of a map as top level keys in the serialised JSON?

A possible way to solve your issue is create a custom serializer for your MyClass class and annotate your class with the JsonSerialize annotation:

@JsonSerialize(using = MyClassSerializer.class)
public class MyClass {
    private String id;
    private Map<String, Object> properties;
}

In the custom serializer you can iterate over the properties map and build the representation of your object like below:

public class MyClassSerializer extends JsonSerializer<MyClass> {

    @Override
    public void serialize(MyClass t, JsonGenerator jg, SerializerProvider sp) throws IOException {
        jg.writeStartObject();
        jg.writeStringField("id", t.getId());
        for (Map.Entry<String, Object> entry : t.getProperties().entrySet()) {
            jg.writeObjectField(entry.getKey(), entry.getValue());
        }
        jg.writeEndObject();
    }
}

An example using your data :

public class Main {

    public static void main(String[] args) throws JsonProcessingException {
        MyClass mc = new MyClass();
        Map<String, Object> properties = Map.of(
                "fruit", "apple",
                "color", "red"
        );
        mc.setId("myid");
        mc.setProperties(properties);
        System.out.println(mc);
        ObjectMapper mapper = new ObjectMapper();
        //it will print {"id":"myid","color":"red","fruit":"apple"}
        System.out.println(mapper.writeValueAsString(mc));
    }
}
dariosicily
  • 4,239
  • 2
  • 11
  • 17
-1

The annotation @JsonUnwrapped does exactly what you are looking for.

flyinaway
  • 17
  • 7