0

I have the following JSON:

{
  "code":1000,
  "message":"Success",
  "data":{
    "results":[
      {
        "lineId":"C4000LG2020253739",
        "lineDiagnostics":{
          "C4000LG2020253739":{
            "ap":{
              "broadbanddsthroughput":{
                "broadbandDsThroughput":[
                  {
                    "average":104830,
                    "std":0,
                    "detection":0,
                    "numErrorFreeSamples":1,
                    "sampleMaxPercentile":107673,
                    "latestSampleTimestamp":1698160893000,
                    "sampleMax":107673,
                    "url":"http://blah-blah.com",
                    "videoQuality":7,
                    "serviceDetection":-1,
                    "percentile":[
                      104830
                    ],
                    "latestSample":104830,
                    "primaryIp":"205.171.3.100",
                    "speedTestTrafficMB":56.9910995
                  }
                ]
              },
              "broadbandusthroughput":{
                "broadbandUsThroughput":[
                  {
                    "average":37828,
                    "std":0,
                    "numErrorFreeSamples":1,
                    "sampleMaxPercentile":38393,
                    "latestSampleTimestamp":1698160893000,
                    "sampleMax":38393,
                    "url":"http://blah-blah.com",
                    "serviceDetection":-1,
                    "percentile":[
                      37828
                    ],
                    "latestSample":37828,
                    "primaryIp":"205.171.3.100",
                    "speedTestTrafficMB":21.8231345
                  }
                ]
              }
            },
            "interface":{
              
            },
            "station":{
              
            },
            "multiWan":{
              
            }
          }
        },
        "analysisDay":20231024
      }
    ]
  }
}

Under the lineDiagnostics, we have the "C4000LG2020253739": {...} and I need the contents from inside this object for my further calculations, could anyone please let me know how can this be achieved?

I am using Jackson to map the JSON values to a Java class.

Note: This particular string value "C4000LG2020253739":{...} will change with every microservice call(and not the contents inside this{...}), so I am facing problem with creating a general purpose Java class for this JSON structure.

I am using Jackson to map the JSON values to a Java class:

public class Class1{
    //historical speed response structure : map from json response
    String code;
    String message;

    @JsonProperty("data")
    DataSpeeds dataSpeeds;
...}

public class DataSpeeds {
    @JsonProperty("results")
    List<Results> results;

    @JsonProperty("lineId")
    String lineId;
...}

public class Results {

    String lineId;

    @JsonProperty("lineDiagnostics")
    LineDiagnostics lineDiagnostics;
...}

public class LineDiagnostics {
    @JsonProperty("ap")
    Ap ap;
...}

Inside the LineDiagnostics object, I need to map the "C4000LG2020253739":{...} from JSON, how can this be done? any pointers?

2
  • 3
    Just map your LineDiagnostics object to a HashMap. Commented Nov 2, 2023 at 4:32
  • 1
    Though @RobbyCornelissen has already mentioned it, I would like to expand on it. In the Result class, change the type of the field lineDiagnostics to Map<String, LineDiagnostics> from plain LineDiagnostics. Jackson will then populate the keys of this map with C4000LG2020253739, etc. and the values as the corresponding unmarshalled LineDiagnostics instances. Commented Nov 2, 2023 at 5:26

1 Answer 1

1

Option 1

At least you can deserialize json to Map and retrieve required data from it.

public static Map<String, Object> getLineDiagnosticByLineId(File file, String lineId) throws IOException {
    TypeReference<HashMap<String, Object>> typeRef = new TypeReference<>() {
    };

    Map<String, Object> map = new ObjectMapper().readValue(file, typeRef);
    Map<String, Object> data = (Map<String, Object>) map.getOrDefault("data", Map.of());
    List<Object> results = (List<Object>) data.getOrDefault("results", List.of());

    return results.stream()
            .map(result -> (Map<String, Object>) result)
            .filter(result -> lineId.equals(result.get("lineId")))
            .map(result -> result.getOrDefault("lineDiagnostics", List.of()))
            .map(lineDiagnostics -> (Map<String, Object>) lineDiagnostics)
            .findFirst().orElse(Map.of());
}

Option 2

But I recommend you to build a model and use it instead of Map.

Simple model could look like this:

@Getter
@Setter
public class DataModel {

    private Integer code;
    private String message;
    private Data data;

    @Getter
    @Setter
    public static class Data {

        private List<Result> results;

    }

    @Getter
    @Setter
    public static class Result {

        private String lineId;
        private Map<String, Object> lineDiagnostics;
        private Integer analysisDay;

    }

}

And your business code like:

public static Map<String, Object> getLineDiagnosticByLineId(File file, String lineId) throws IOException {
    DataModel dataModel = new ObjectMapper().readValue(file, DataModel.class);
    return dataModel.getData().getResults().stream()
            .filter(result -> lineId.equals(result.getLineId()))
            .map(DataModel.Result::getLineDiagnostics)
            .findFirst().orElse(Map.of());
}

Option 3

And finally. You can solve your problem with mup Map<String, Object> inside LineDiagnostics and define setter with @JsonAnySetter annotation.

@Getter
@Setter
public class DataModel {

    private Integer code;
    private String message;
    private Data data;

    @Getter
    @Setter
    public static class Data {

        private List<Result> results;

    }

    @Getter
    @Setter
    public static class Result {

        private String lineId;
        private LineDiagnostics lineDiagnostics;
        private Integer analysisDay;

    }

    @Getter
    @Setter
    public static class LineDiagnostics {

        private Map<String, LineDiagnostic> lineDiagnostics = new HashMap<>();

        @JsonAnySetter
        public void setLineDiagnostic(String key, LineDiagnostic value) {
            lineDiagnostics.put(key, value);
        }

    }

    @Getter
    @Setter
    public static class LineDiagnostic {

        private Ap ap;
        @JsonProperty("interface")
        private Object anInterface;
        private Object station;
        private Object multiWan;

    }

    @Getter
    @Setter
    public static class Ap {

        @JsonProperty("broadbanddsthroughput")
        private BroadbandDsThroughput broadbandDsThroughput;
        @JsonProperty("broadbandusthroughput")
        private BroadbandUsThroughput broadbandUsThroughput;

    }

    @Getter
    @Setter
    public static class BroadbandDsThroughput {

        private List<BroadbandThroughput> broadbandDsThroughput;

    }

    @Getter
    @Setter
    public static class BroadbandUsThroughput {

        private List<BroadbandThroughput> broadbandUsThroughput;

    }

    @Getter
    @Setter
    public static class BroadbandThroughput {

        private Double average;
        private Double std;
        private Double detection;
        private Integer numErrorFreeSamples;
        private Integer sampleMaxPercentile;
        private Long latestSampleTimestamp;
        private Integer sampleMax;
        private String url;
        private Integer videoQuality;
        private Integer serviceDetection;
        private List<Integer> percentile;
        private Integer latestSample;
        private String primaryIp;
        @JsonProperty("speedTestTrafficMB")
        private Double speedTestTrafficMb;

    }

}

And your final result should look like this:

public static DataModel.LineDiagnostics getLineDiagnosticByLineId(File file, String lineId) throws IOException {
    DataModel dataModel = new ObjectMapper().readValue(file, DataModel.class);
    
    return dataModel.getData().getResults().stream()
            .filter(result -> lineId.equals(result.getLineId()))
            .map(DataModel.Result::getLineDiagnostics)
            .findFirst().orElse(null);
}
Sign up to request clarification or add additional context in comments.

1 Comment

That's a great answer! I was looking for to such a POJO. Maybe one 's' you missed at: @JsonAnySetter setLineDiagnostics(...) This solved my problem. Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.