How to map json response object to a preferred format using Jackson / other library?

15,740

You are using JAX-RS annotations instead of the Spring web service annotations. You can make this work, but I would recommend going with the default Spring annotations because those are all autoconfigured for you if you're using the spring boot starter dependencies.

First thing - you need to create classes that are set up like the request and response. Something like this:

public class ThirdPartyResponse {   
    MetaData meta;
    Response response;
}

public class Response {
    List<Location> locations;
}

public class MetaData {
    String code;
    String requestId;    
}

public class Location {
    String id;
    String name;
    Contact contact;
    LocationDetails location;
}

public class Contact {
    String phone;
    String email;
}

public class LocationDetails {
    List<String> address;
}

You can use Jackson annotations to customize the deserialization, but by default it maps pretty logically to fields by name and the types you might expect (a JSON list named "locations" gets mapped to a List in your object named "locations", etc).

Next you'll want to use a @RestController annotated class for your service, which makes the service call to the third party service using RestTemplate, something like:

@RestController
public class Controller {

    @Value("${url}")
    String url;

    @RequestMapping("/path"
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public List<Location> locations(@RequestParam String query) {

        // RestTemplate will make the service call and handle the 
        // mapping from JSON to Java object

        RestTemplate restTemplate = new RestTemplate();
        ThirdPartyResponse response = restTemplate.getForObject(url, ThirdPartyResponse.class);

        List<Location> myResponse = new List<>();            

        // ... do whatever processing you need here ...

        // this response will be serialized as JSON "automatically"
        return myResponse;
    }
}

As you can see, Spring Boot abstracts away a lot of the JSON processing and makes it pretty painless.

Take a look at Spring's guides which are pretty helpful:

Consuming a service with RestTemplate http://spring.io/guides/gs/consuming-rest/

Creating a web service using @RestController https://spring.io/guides/gs/rest-service/

Share:
15,740
philomath
Author by

philomath

Sharing is caring

Updated on June 29, 2022

Comments

  • philomath
    philomath almost 2 years

    I am getting the below JSON response format from a third party web service:

    {
        "meta": {
            "code": 200,
            "requestId": "1"
        },
        "response": {
            "locations": [
                {
                    "id": "1",
                    "name": "XXX",
                    "contact": {
                        phone: '123',
                        email: 'abc'
                    },
                    "location": {
                        "address": [
                            "Finland"
                        ]
                    }
                },
                {
                    // another location
                }
            ]
        }
    }
    

    And here is what I should return as a response from my own web service:

    [
        {
            "id": "1",
            "name": "XXX",
            "phone": '123',
            "address": "Finland"
        },
        {
            // another location
        }
    ]
    

    What should I do? I've read some good stuff about Jackson but there are only a few simple examples where you map some simple JSON obj as is to POJO. In my case, I need to remove a few nodes, and also traverse deeper down the hierarchy to get the nested value. This is my baby step so far in my spring boot app:

        @GET
        @Path("{query}")
        @Produces("application/json")
        public String getVenues(@PathParam("query") String query){
            return client.target(url).queryParam("query",query).request(...).get(String.class)
        }
    

    Any helps, pointers, recommendations are welcomed!

  • nerdherd
    nerdherd over 8 years
    Although a reasonable general approach, this doesn't take advantage of anything Spring or Spring Boot offers.
  • philomath
    philomath over 8 years
    Thanks for your answer. Following your instruction, I'am able to get back {"id": "1", "name": "XXX"} fairly easily. But how can I get back "phone" and "address" properties? I'm not sure how much involved/manual processing I need to do that.
  • nerdherd
    nerdherd over 8 years
    @GreatQuestion I added a few more details, but basically you need to keep adding more classes to fully align with the response you're getting back in the JSON. For every JSON object you need a class, and for JSON lists you use a List<SomeClass>.
  • philomath
    philomath over 8 years
    That's why I ask, since I can see that this approach could be quite cumbersome and require us to create a bunch of models if you have to get very nested properties. In this case, we only need to get back List<Location>, but we have to create ThirdPartyResponse, MetaData, Response, Contact, LocationDetails ...
  • nerdherd
    nerdherd over 8 years
    You don't need to include classes or fields for things you don't care about. I find for nested responses I typically use inner static classes to keep all the nesting pretty localized, and that's easier than trying to manually parse it. Jackson will also parse to Maps if you don't want to create domain objects. It's a little uglier but very flexible. To my knowledge Jackson doesn't really give you ways to extract specific values because it uses streaming parsing, which means it doesn't keep the full representation in memory and so doesn't offer arbitrary node retrieval.