0

I can't figure out how to handle nested JSON values in my Java classes. To make it simple as possible, I created four Java classes with every 'nested level'. However, I'm trying to have all these values in one Java class. How can I do this?

Json:

{
   "_embedded":{
      "events":[
         {
            "name":"KISS | End Of The Road World Tour",
            "dates":{
               "start":{
                  "dateTime":"2021-06-12T19:00:00Z"
               },
               "classifications":[
                  {
                     "name":"Rock"
                  }
               ],
               "_embedded":{
                  "venues":[
                     {
                        "name":"Atlas Arena"
                     }
                  ]
               }
            }
         }
      ]
   }
}

Java classes:

@Data
public class EventList {

    @JsonProperty("_embedded")
    private Events events;
}


@Data
public class Events {

    @JsonProperty("events")
    public List<EventDetails> eventsList;
}

@Data
public class EventDetails {

    private String name;
    @JsonProperty("dates.start.dateTime")
    private String startDate;
    @JsonProperty("classifications.genre.name")
    private String musicType;
    @JsonProperty("_embedded.venues")
    private List<Venues> eventPlaceName;
}

@Data
public class Venues {

    private String name;
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • Does this answer your question? [How to map a nested value to a property using Jackson annotations?](https://stackoverflow.com/questions/37010891/how-to-map-a-nested-value-to-a-property-using-jackson-annotations) – Nowhere Man Oct 04 '20 at 00:29
  • 1
    What do you mean with _"I'm trying to have all these values in one Java class"_? Could you show what you think that single class would look like? – Mark Rotteveel Oct 04 '20 at 08:31

1 Answers1

1

You can club all the supporting classes in one class like below :

@Data
public class Start {
    @JsonProperty("dateTime")
    public Date dateTime;

    public static class Venue {
        @JsonProperty("name")
        public String name;
    }

    @Data
    public static class Classification {
        @JsonProperty("name")
        public String name;
    }

    @Data
    public static class Embedded2 {
        @JsonProperty("venues")
        public List<Venue> venues;
    }

    @Data
    public static class Dates {
        @JsonProperty("start")
        public Start start;
        @JsonProperty("classifications")
        public List<Classification> classifications;
        @JsonProperty("_embedded")
        public Embedded2 _embedded;
    }

    @Data
    public static class Event {
        @JsonProperty("name")
        public String name;
        @JsonProperty("dates")
        public Dates dates;
    }

    @Data
    public static class Embedded {
        @JsonProperty("events")
        public List<Event> events;
    }

    @Data
    public static class Root {
        @JsonProperty("_embedded")
        public Embedded _embedded;
    }
}

You can test (I am using Jackson for deserialization)
create ObjectMapper class and deserialize into a Root class

public class TestJson {
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Start.Root root = objectMapper.readValue(new File("C:\\Anurag\\Development\\CodeBase\\demo\\src\\main\\java\\com\\example\\demo\\domain\\testJson\\test.json"), Start.Root.class);
            System.out.println(root);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

-When debugging, you'll notice that our objects have been filled accordingly: enter image description here

**Changes done as per your requiement **

@Data
public class EventList {

    @Getter
    @JsonProperty("_embedded")
    private Events events;




    @Data
    public static class Venue {
        @JsonProperty("name")
        public String name;
    }

    @Data
    public static class Classification {
        @JsonProperty("name")
        public String name;
    }

    @Data
    public static class Embedded2 {
        @JsonProperty("venues")
        public List<Venue> venues;
    }

    @Data
    public static class Dates {
        @JsonProperty("start")
        public Start start;
        @JsonProperty("classifications")
        public List<Classification> classifications;
        @JsonProperty("_embedded")
        public Embedded2 _embedded;
    }

    @Data
    public static class EventDetails {
        @JsonProperty("name")
        public String name;
        @JsonProperty("dates")
        public Dates dates;
    }

    @Data
    public static class Events {
        @JsonProperty("events")
        public List<EventDetails> eventsList;
    }

    @Data
    public static class Start {
        @JsonProperty("dateTime")
        public Date dateTime;
    }


}

public class TestJson {
    public static void main(String[] args) {
        List<EventList.EventDetails> anyCity = findEventByCity("any city");
        anyCity.stream().forEach(p-> {
            System.out.println(p);
        });

    }

    @SneakyThrows
    static List<EventList.EventDetails> findEventByCity(String city) {
        ObjectMapper objectMapper = new ObjectMapper();
        EventList eventList = objectMapper.readValue(new File("C:\\Anurag\\Development\\CodeBase\\demo\\src\\main\\java\\com\\example\\demo\\domain\\testJson\\test.json"), EventList.class);
        List<EventList.EventDetails> eventsList = eventList.getEvents().getEventsList();
        return eventsList;
    }

    }

ebugging, you'll notice that our objects have been filled accordingly:

anurag saxena
  • 277
  • 1
  • 3
  • 10
  • Thanks! Do people use similar solutions in commercial projects? Is it good practice? And last question: my method in controller was: @GetMapping public List findEventByCity(@RequestParam String city) { EventList eventList = restTemplate.getForObject(API_URL + city, EventList.class); return eventList.getEvents().getEventsList(); } How should I modify it after your changes? – sir_crazy_pancake Oct 04 '20 at 12:08
  • @sir_crazy_pancake yes I have seen this pattern in most of the production-ready code, in my current and as well as in previous companies, as for as you controller method, I have updated the code as a basic method, you may easily convert to contoller with minimal change. – anurag saxena Oct 05 '20 at 04:13
  • Thanks, I'm really grateful! – sir_crazy_pancake Oct 05 '20 at 15:09