skip to Main Content

I have 2 queries that return the same object for earliest and latest datasets.

eg :

earliestDataset = [
{'id' : 123, 'highlights': 2, 'created_date': 2024-01-01, 'saves':5, 'wins':3},
{'id' : 124, 'highlights': 3, 'created_date': 2024-01-03, 'saves':2, 'wins':1},
{'id' : 253, 'highlights': 5, 'created_date': 2024-02-02, 'saves':3, 'wins':7}]
latestDataset = [
{'id' : 123, 'highlights': 6, 'created_date': 2024-04-01, 'saves':22, 'wins':14},
{'id' : 124, 'highlights': 9, 'created_date': 2024-04-03, 'saves':8, 'wins':9},
{'id' : 253, 'highlights': 12, 'created_date': 2024-03-02, 'saves':15, 'wins':20}]

I wanted to merge the datasets and return in new json format such as :

{
  "id": "123",
  "highlights": [
    {
      "earliest": "2",
      "latest": "6",
      "difference": "+4"
    }
  ],
  "created_date": [
    {
      "earliest": "2024-01-01",
      "latest": "2024-04-01"
    }
  ],
  "saves": [
    {
      "earliest": "5",
      "latest": "22",
      "difference": "+17"
    }
  ],
  "wins": [
    {
      "earliest": "7",
      "latest": "20",
      "difference": "+13"
    }
  ]
}

I don’t know if I should use map or stream to compare both list, find id and map the values into new Json object. Any help much appreciated, thanks in advance!

2

Answers


  1. I think the best choice is to use Map with Jackson.

    public class Foo {
    
        @Data
        public static final class Event {
    
            private int id;
            private int highlights;
            @JsonProperty("created_date")
            @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
            private Date createdDate;
            private int saves;
            private int wins;
    
        }
    
        @Data
        @Builder
        public static final class MergeEvent {
    
            private int id;
            private Range highlights;
            @JsonProperty("created_date")
            private Range createdDate;
            private Range saves;
            private Range wins;
    
            @Data
            @Builder
            @JsonInclude(JsonInclude.Include.NON_NULL)
            public static final class Range {
    
                private String earliest;
                private String latest;
                private String difference;
    
            }
    
        }
    
        public static void main(String... args) throws JsonProcessingException {
            String jsonEarlies = "[n" +
                    "   {n" +
                    "      "id":123,n" +
                    "      "highlights":2,n" +
                    "      "created_date":"2024-01-01",n" +
                    "      "saves":5,n" +
                    "      "wins":3n" +
                    "   },n" +
                    "   {n" +
                    "      "id":124,n" +
                    "      "highlights":3,n" +
                    "      "created_date":"2024-01-03",n" +
                    "      "saves":2,n" +
                    "      "wins":1n" +
                    "   },n" +
                    "   {n" +
                    "      "id":253,n" +
                    "      "highlights":5,n" +
                    "      "created_date":"2024-02-02",n" +
                    "      "saves":3,n" +
                    "      "wins":7n" +
                    "   }n" +
                    "]";
            String jsonLatest = "[n" +
                    "   {n" +
                    "      "id":123,n" +
                    "      "highlights":6,n" +
                    "      "created_date":"2024-04-01",n" +
                    "      "saves":22,n" +
                    "      "wins":14n" +
                    "   },n" +
                    "   {n" +
                    "      "id":124,n" +
                    "      "highlights":9,n" +
                    "      "created_date":"2024-04-03",n" +
                    "      "saves":8,n" +
                    "      "wins":9n" +
                    "   },n" +
                    "   {n" +
                    "      "id":253,n" +
                    "      "highlights":12,n" +
                    "      "created_date":"2024-03-02",n" +
                    "      "saves":15,n" +
                    "      "wins":20n" +
                    "   }n" +
                    "]";
    
            String json = merge(jsonEarlies, jsonLatest);
            System.out.println(json);
        }
    
        public static String merge(String jsonEarliest, String jsonLatest) throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            Map<Integer, Event> earliest = readEventsAndGroupById(objectMapper, jsonEarliest);
            Map<Integer, Event> latest = readEventsAndGroupById(objectMapper, jsonLatest);
            List<MergeEvent> mergeEvents = merge(earliest, latest);
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mergeEvents);
        }
    
        private static Map<Integer, Event> readEventsAndGroupById(ObjectMapper mapper,
                                                                  String json) throws JsonProcessingException {
            List<Event> events = mapper.readValue(json, new TypeReference<>() {
            });
            return events.stream().collect(Collectors.toMap(Event::getId, Function.identity()));
        }
    
        private static List<MergeEvent> merge(Map<Integer, Event> earliest,
                                              Map<Integer, Event> latest) {
            return Stream.concat(earliest.keySet().stream(), latest.keySet().stream())
                    .distinct()
                    .map(id -> merge(id, earliest.get(id), latest.get(id)))
                    .sorted(Comparator.comparingInt(MergeEvent::getId))
                    .collect(Collectors.toList());
        }
    
        private static MergeEvent merge(int id, Event earliest, Event latest) {
            return MergeEvent.builder()
                    .id(id)
                    .highlights(calcRange(earliest.getHighlights(), latest.getHighlights()))
                    .createdDate(calcRange(earliest.getCreatedDate(), latest.getCreatedDate()))
                    .saves(calcRange(earliest.getSaves(), latest.getSaves()))
                    .wins(calcRange(earliest.getWins(), latest.getWins()))
                    .build();
        }
    
        private static MergeEvent.Range calcRange(int earliest, int latest) {
            return MergeEvent.Range.builder()
                    .earliest(String.valueOf(earliest))
                    .latest(String.valueOf(latest))
                    .difference(earliest == latest ? null : String.format("%+d", latest - earliest))
                    .build();
        }
    
        private static MergeEvent.Range calcRange(Date earliest, Date latest) {
            return MergeEvent.Range.builder()
                    .earliest(String.format("%1$tY-%1$tm-%1$td", earliest))
                    .latest(String.format("%1$tY-%1$tm-%1$td", latest))
                    .build();
        }
    
    }
    

    Output:

    [ {
      "id" : 123,
      "highlights" : {
        "earliest" : "2",
        "latest" : "6",
        "difference" : "+4"
      },
      "saves" : {
        "earliest" : "5",
        "latest" : "22",
        "difference" : "+17"
      },
      "wins" : {
        "earliest" : "3",
        "latest" : "14",
        "difference" : "+11"
      },
      "created_date" : {
        "earliest" : "2024-01-01",
        "latest" : "2024-04-01"
      }
    }, {
      "id" : 124,
      "highlights" : {
        "earliest" : "3",
        "latest" : "9",
        "difference" : "+6"
      },
      "saves" : {
        "earliest" : "2",
        "latest" : "8",
        "difference" : "+6"
      },
      "wins" : {
        "earliest" : "1",
        "latest" : "9",
        "difference" : "+8"
      },
      "created_date" : {
        "earliest" : "2024-01-03",
        "latest" : "2024-04-03"
      }
    }, {
      "id" : 253,
      "highlights" : {
        "earliest" : "5",
        "latest" : "12",
        "difference" : "+7"
      },
      "saves" : {
        "earliest" : "3",
        "latest" : "15",
        "difference" : "+12"
      },
      "wins" : {
        "earliest" : "7",
        "latest" : "20",
        "difference" : "+13"
      },
      "created_date" : {
        "earliest" : "2024-02-02",
        "latest" : "2024-03-02"
      }
    } ]
    
    Login or Signup to reply.
  2. You may try JSON library Josson to do transformation.

    https://github.com/octomix/josson

    Map<String, JsonNode> params = Map.of(
        "$earliest", Josson.readJsonNode("[" +
            "{"id": 123, "highlights": 2, "created_date": "2024-01-01", "saves":5, "wins":3}," +
            "{"id": 124, "highlights": 3, "created_date": "2024-01-03", "saves":2, "wins":1}," +
            "{"id": 253, "highlights": 5, "created_date": "2024-02-02", "saves":3, "wins":7}]"),
        "$latest", Josson.readJsonNode("[" +
            "{"id": 123, "highlights": 6, "created_date": "2024-04-01", "saves":22, "wins":14}," +
            "{"id": 124, "highlights": 9, "created_date": "2024-04-03", "saves":8, "wins":9}," +
            "{"id": 253, "highlights": 12, "created_date": "2024-03-02", "saves":15, "wins":20}]"),
        "$id", IntNode.valueOf(123)
    );
    JsonNode node = Josson.create().getNode(
        "map(e: $earliest.[id=$id], l: $latest.[id=$id])" +
        ".map(id: $id," +
        "     highlights: wrap(map(earliest:e.highlights, latest:l.highlights, difference:calc(y-x, x:e.highlights, y:l.highlights).formatText('%+.0f')))," +
        "     created_date: wrap(map(earliest:e.created_date, latest:l.created_date))," +
        "     saves: wrap(map(earliest:e.saves, latest:l.saves, difference:calc(y-x, x:e.saves, y:l.saves).formatText('%+.0f')))," +
        "     wins: wrap(map(earliest:e.wins, latest:l.wins, difference:calc(y-x, x:e.wins, y:l.wins).formatText('%+.0f')))" +
        ")",
        params);
    System.out.println(node.toPrettyString());
    

    Output

    {
      "id" : 123,
      "highlights" : [ {
        "earliest" : 2,
        "latest" : 6,
        "difference" : "+4"
      } ],
      "created_date" : [ {
        "earliest" : "2024-01-01",
        "latest" : "2024-04-01"
      } ],
      "saves" : [ {
        "earliest" : 5,
        "latest" : 22,
        "difference" : "+17"
      } ],
      "wins" : [ {
        "earliest" : 3,
        "latest" : 14,
        "difference" : "+11"
      } ]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search