springspring-restspring-webclient

how to get the first list item from a json response using the spring webclient


I am getting below response in rest API and want to parse and return the first list item using the spring webclient.

JSON Response

{"_embedded":{"service":[{"id":101,"serviceModelUUID":"aaa8884883","action":"create"},{"id":102,"serviceModelUUID":"aaa8884884","action":"delete"}]}}

I want to return below response

[{"id":101,"serviceModelUUID":"aaa8884883","action":"create"},{"id":102,"serviceModelUUID":"aaa8884884","action":"delete"}]

below is my spring webclient code which is returning single list with null field values

private <T> List<T> getMultipleResources(Class<T> clazz, URI uri) {
    return webClient.get().uri(uri).retrieve().bodyToFlux(clazz).collectList().block();
}

Solution

  • Unpack needed field from your initial response and use constructParametricType to have JavaType for a list of instances of the passed Class<T>

    A wrapper around the data you need. Here, you extract only the required field (_embedded.service).

    class DataWrapper {
        private Object data;
    
        public Object getData() {
            return data;
        }
    
        @JsonProperty("_embedded")
        private void unpackEmbedded(Map<String, Object> embedded) {
            this.data = embedded.get("service");
        }
    }
    

    And construct JavaType to specify the expected data type returned by the endpoint.

    private void howToUse() {
        List<Service> res1 = getMultipleResources(URI.create("/"), Service.class);
        // prints for your example
        // [{id=101, serviceModelUUID=aaa8884883, action=create}, {id=102, serviceModelUUID=aaa8884884, action=delete}]
        System.out.println(res1);
        // create
        System.out.println(res1.getFirst().getAction());
    }
    
    private <T> List<T> getMultipleResources(URI uri, Class<T> clazz) {
        var wrapperRef = new ParameterizedTypeReference<DataWrapper>() {};
        var data = webClient.get().uri(uri).retrieve().bodyToMono(wrapperRef).block().getData();
        // better to make an objectMapper as a property of service where getMultipleResources is defined
        var objectMapper = new ObjectMapper();
        var dataType = objectMapper.getTypeFactory().constructParametricType(List.class, clazz);
        return objectMapper.convertValue(data, dataType);
    }
    

    Dont forget to define you class - Service