Java/Jackson JSON serialisation: How to write Map<String,Object> to Array of objects?

1.5k Views Asked by At

I have a POJO in my Java project which has a field with datatype Map<String, Object>:

@Data
@NoArgsConstructor
public class B {
    private Map<String,Object> dummyField;
}

Currently, while serializing the JSON using the Jackson the field has been written as:

"dummyField" : {
    "Google" : "https://google.com",
    "yt" : "https://yt.com"
  }

I would like to know if there is a way in Jackson to serialize this field something like this,

"dummyField" : [
    {
     "Google" : "https://google.com"
    },
    {
     "yt" : "https://yt.com"
    }
  ]

I am aware that I can achieve this using the custom serializer. I was hoping to know if there is any direct way for Jackson to achieve this.

1

There are 1 best solutions below

0
On

According to default implementation of MapSerializer it creates new JSON object gen.writeStartObject(value) always. There is no ability to configure array creation instead.
Default implemetation of MapSerializer:

    @Override
    public void serialize(Map<?,?> value, JsonGenerator gen, SerializerProvider provider) throws IOException
    {
        gen.writeStartObject(value);
        serializeWithoutTypeInfo(value, gen, provider);
        gen.writeEndObject();
    }

The custom serializer is more efficient solution.
But the alternative solution to achieve such serialization - is simply to convert Map to the Set<Map.Entry>
Solution 1, @JsonGetter with converting Map->Set

@Data
@NoArgsConstructor
public class B {
    private Map<String,Object> dummyField = new HashMap<>();

    @JsonGetter("dummyField")
    public Set<Map.Entry<String,Object>> getDummyFieldEntrySet() {
        return dummyField.entrySet();
    }

    @JsonSetter("dummyField")
    public void setDummyFieldEntrySet(Set<Map.Entry<String,Object>> value) {
        dummyField = value.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
 }
}

Solution 2, custom type converter Map->Set

@Data
@NoArgsConstructor
public class B {
    @JsonSerialize(converter = MapToSetConverter.class)
    @JsonDeserialize(converter = SetToMapConverter.class)
    private Map<String,Object> dummyField = new HashMap<>();
}

public class MapToSetConverter extends StdConverter<Map<?,?>, Set<? extends Map.Entry<?,?>>> {
    @Override
    public Set<? extends Map.Entry<?,?>> convert(Map<?,?> value) {
        return value.entrySet();
    }
}

public class SetToMapConverter extends StdConverter<Set<? extends Map.Entry<?,?>>, Map<?,?>> {
    @Override
    public Map<?,?> convert( Set<? extends Map.Entry<?,?>> value) {
        return value.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
}