3

I have problem with parsing json array to java collection of specified objects.

JSON response:

{
  "data": [
    {
      "country_code": "US", 
      "name": "United States", 
      "supports_region": "true", 
      "supports_city": "true"
    }, 
    {
      "country_code": "CA", 
      "name": "Canada", 
      "supports_region": "true", 
      "supports_city": "true"
    }, 
    {
      "country_code": "GB", 
      "name": "United Kingdom", 
      "supports_region": "true", 
      "supports_city": "true"
    }
  ]
}

Next I have class of single country:

@JsonIgnoreProperties(ignoreUnknown = true)
public class TargetCountry {

    @JsonProperty("country_code")
    private String countryCode;

    @JsonProperty("name")
    private String name;

    public String getCountryCode() {
        return countryCode;
    }

    public String getName() {
        return name;
    }

}

I'm using Jackson library to parse json into java. Everything would be fine if there won't be extra field "data" which wraps array. I don't want to make additionally wrapper class due to "data" field. How can I parse that response in elegant way to receive: Collection<TargetCountry> for example:

RestTemplate restTemplate = new RestTemplate();
TargetCountry[] countryList = restTemplate.getForObject(uri, TargetCountry[].class);
apo
  • 116
  • 7

1 Answers1

1

You can consider two options:

  • Customizing the Jackson object mapper for your rest template instance in a way that it would ignore the root "data" node using the withRootName() method. You may need to consult with this question how to customize the mapper.
  • Read the result as a JsonNode, skip the "data" path and covert it to the object array.

Here are example:

public class JacksonRootValue {
    public static final String JSON = "{\n" +
            "  \"data\": [\n" +
            "    {\n" +
            "      \"country_code\": \"US\", \n" +
            "      \"name\": \"United States\", \n" +
            "      \"supports_region\": \"true\", \n" +
            "      \"supports_city\": \"true\"\n" +
            "    }, \n" +
            "    {\n" +
            "      \"country_code\": \"CA\", \n" +
            "      \"name\": \"Canada\", \n" +
            "      \"supports_region\": \"true\", \n" +
            "      \"supports_city\": \"true\"\n" +
            "    }, \n" +
            "    {\n" +
            "      \"country_code\": \"GB\", \n" +
            "      \"name\": \"United Kingdom\", \n" +
            "      \"supports_region\": \"true\", \n" +
            "      \"supports_city\": \"true\"\n" +
            "    }\n" +
            "  ]\n" +
            "}";

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class TargetCountry {
        @JsonProperty("country_code")
        public String countryCode;
        public String name;

        @Override
        public String toString() {
            return "TargetCountry{" +
                    "countryCode='" + countryCode + '\'' +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper1 = new ObjectMapper();
        // customize the mapper
        mapper1.setConfig(mapper1.getDeserializationConfig().withRootName("data"));
        TargetCountry[] result1 = mapper1.readValue(JSON, TargetCountry[].class);
        System.out.println("Option 1: " + Arrays.toString(result1));

        // read as a JsonNode and then convert to an object
        ObjectMapper mapper2 = new ObjectMapper();
        JsonNode node = mapper2.readValue(JSON, JsonNode.class);
        TargetCountry[] result2 = mapper2.treeToValue(node.path("data"), TargetCountry[].class);
        System.out.println("Option 2: " + Arrays.toString(result2));
    }
}

Output:

Option 1: [TargetCountry{countryCode='US', name='United States'}, TargetCountry{countryCode='CA', name='Canada'}, TargetCountry{countryCode='GB', name='United Kingdom'}]
Option 2: [TargetCountry{countryCode='US', name='United States'}, TargetCountry{countryCode='CA', name='Canada'}, TargetCountry{countryCode='GB', name='United Kingdom'}]
Community
  • 1
  • 1
Alexey Gavrilov
  • 10,593
  • 2
  • 38
  • 48