0

Let's say I have the following object.

class Foo {

    private String name;
    private int age;
    private Map<String, object> extra;

}

public static void main(String[] args) {
    Foo foo = new Foo();
    foo.name = "adam";
    foo.age = 25;
    foo.extra.put("hobbies", /** list of hobbies **/)
    foo.extra.put("firends", /** list of friends **/)

    // convert to json...
}

and I want the following output... Is it possible to do this by using custom serialize?

{
    "name": "adam",
    "age": 25,
    "hobbies": [
      {
         "name": "footbal",
         "level":  1
      }
      { 
        "name": "coding",
        "level": 2
      }
    ],
    "friends": [
      {
        "id": 1
        "name": "jack"
      },
      {
        "id": 2
        "name": "rose"
      }
    ]
}
Jongz Puangput
  • 5,527
  • 10
  • 58
  • 96

3 Answers3

1

I have found a way to achieve. by using a combination of @JsonIgnore @JsonAnyGetter for Map, but if you have just custom object you can use only @JsonUnwrapped to get the same behavior.

class Foo {

    private String name;
    private int age;

    @JsonIgnore
    private Map<String, Object> extra;

    @JsonAnyGetter
    public Map<String, Object> getExtra() {
       return extra;
    }
}
Jongz Puangput
  • 5,527
  • 10
  • 58
  • 96
  • `@JsonIgnore` should not be required. Also, take a look on similar problems and how they were solved. `@JsonAnyGetter` and `@JsonUnwrapped` are really powerful. [Wrapping Json fields](https://stackoverflow.com/questions/54370637/wrapping-json-fields-into-instance-variable-of-a-pojo/54373637#54373637), [Adding a dynamic json property as java pojo](https://stackoverflow.com/questions/56245719/adding-a-dynamic-json-property-as-java-pojo-for-jackson/56247021#56247021), [dynamic prop](https://stackoverflow.com/questions/55684724/how-to-use-dynamic-property-names-for-a-json-object/55687330#55687330) – Michał Ziober Sep 16 '19 at 13:44
  • In my case without `@JsonIgnore`, extra will expose in JSON with its Map member – Jongz Puangput Sep 17 '19 at 03:17
  • Which version of `Jackson` do you use? – Michał Ziober Sep 17 '19 at 06:06
0
ObjectMapper objectMapper = new ObjectMapper();

String json = objectMapper.writeValueAsString(foo);
System.out.println(json);

if you want to write the json directly in output strem

ObjectMapper objectMapper = new ObjectMapper();

objectMapper.writeValue(outputStream, foo);
Khaled Baklouti
  • 408
  • 2
  • 7
0

Almost there, hobbies is List of Map and also you need getters and setters

class Foo {

  private String name;
  private int age;
  private List<Map<String, object>> hobbies;

  // Getters and Setters

}

And in main method use ObjectMapper

public static void main(String[] args) {
Foo foo = new Foo();
foo.SetName("adam");
foo.SetAge(25);

Map<String,Object> map1 = Map.of("name","footbal","level",1);  //from jdk-9 you can use Map.of and List.of to create immutable objects
List<Map<String,Object>> hobbies = List.of(map1);      

foo.setHobbies(hobbies);

// Use ObjectMapper to convert object to json

ObjectMapper objectMapper = new ObjectMapper();

String json = objectMapper.writeValueAsString(foo);
System.out.println(json);


}
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • is there anyway by keeping member as OP, and use custom, Serialize to make it. – Jongz Puangput Sep 15 '19 at 22:50
  • No you cannot, this is how you need to do @JongzPuangput – Ryuzaki L Sep 16 '19 at 00:28
  • This does not answer OP's original question of using `Map>` structure and for each nested map, flatten it out to the top level json. What you are suggesting is merely create another class for each nested map. – nabster Jan 26 '22 at 01:44