52

I am trying to figure out if it is possible to pass a JSON object to rest API, Or pass a multiple parameters to that API ? And how to read these parameters in Spring ? Lets assume that the url looks like the below examples :

Ex.1 http://localhost:8080/api/v1/mno/objectKey?id=1&name=saif

Is it valid to pass a JSON object like in the url below ?

Ex.2 http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"}

Questions:

1) Is it possible to pass a JSON object to the url like in Ex.2?

2) How can we pass and parse the parameters in Ex.1?

I tried to write some methods to achieve my goal, but could not find the right solution?

I tried to pass JSON object as @RequestParam

http://localhost:8080/api/v1/mno/objectKey?id=1 There was an unexpected error (type=Unsupported Media Type, status=415). Content type 'null' not supported

http://localhost:8080/api/v1/mno/objectKey/id=1 There was an unexpected error (type=Not Found, status=404). No message available

http://localhost:8080/api/v1/mno/objectKey/%7B%22id%22:1%7D There was an unexpected error (type=Not Found, status=404). No message available

@RequestMapping(value="mno/{objectKey}",
                method = RequestMethod.GET, 
                consumes="application/json")
    public List<Book> getBook4(@RequestParam ObjectKey objectKey) {
        ...
    }

I tried to pass the JSON object as @PathVariable

@RequestMapping(value="ghi/{objectKey}",method = RequestMethod.GET)
    public List<Book> getBook2(@PathVariable ObjectKey objectKey) {
        ...         
    }

I created this object to hold the id parameter and other parameters like name , etc ....

class ObjectKey{
        long id;
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
    }
Arar
  • 1,926
  • 5
  • 29
  • 47
  • What about annotation [@RequestBody](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html) and passing object as body? – bilak Jun 25 '16 at 20:28
  • Any particular reason why you'd want to do it this way? You should be able to get an object out of the request that matches an entity. – ChiefTwoPencils Jun 25 '16 at 20:29
  • Sorry if the example is not accurate, It is just a proof of concept, I want to be able to get list of suggested items from the DB based on a search criteria. I will have a widget that calls the rest API and pass the parameters . But I am trying to focus on the backend part at the moment – Arar Jun 25 '16 at 20:36

4 Answers4

99

(1) Is it possible to pass a JSON object to the url like in Ex.2?

No, because http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"} is not a valid URL.

If you want to do it the RESTful way, use http://localhost:8080/api/v1/mno/objectKey/1/Saif, and define your method like this:

@RequestMapping(path = "/mno/objectKey/{id}/{name}", method = RequestMethod.GET)
public Book getBook(@PathVariable int id, @PathVariable String name) {
    // code here
}

(2) How can we pass and parse the parameters in Ex.1?

Just add two request parameters, and give the correct path.

@RequestMapping(path = "/mno/objectKey", method = RequestMethod.GET)
public Book getBook(@RequestParam int id, @RequestParam String name) {
    // code here
}

UPDATE (from comment)

What if we have a complicated parameter structure ?

"A": [ {
    "B": 37181,
    "timestamp": 1160100436,
    "categories": [ {
        "categoryID": 2653,
        "timestamp": 1158555774
    }, {
        "categoryID": 4453,
        "timestamp": 1158555774
    } ]
} ]

Send that as a POST with the JSON data in the request body, not in the URL, and specify a content type of application/json.

@RequestMapping(path = "/mno/objectKey", method = RequestMethod.POST, consumes = "application/json")
public Book getBook(@RequestBody ObjectKey objectKey) {
    // code here
}
danronmoon
  • 3,814
  • 5
  • 34
  • 56
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Thanks @Andreas , It works :) But I still have some question ? What if we have a complicated parameter structure ? ** "A": [ { "B": 37181, "timestamp": 1160100436, "categories": [ { "categoryID": 2653, "timestamp": 1158555774 }, { "categoryID": 4453, "timestamp": 1158555774 } ] } ] ** – Arar Jun 25 '16 at 20:50
  • 1
    You don't send something like that in a `GET`, you use a `POST`, and include the JSON in the payload, specifying a content type of `application/json`. – Andreas Jun 25 '16 at 20:53
  • Thanks for the last update Andreas, Is it possible to create a POST using JavaScript because I don't want to consume this rest API using a form , I wanted the JavaScript to consume it. – Arar Jun 25 '16 at 21:24
  • 1
    Yes. I'd suggest you do a web search. I'd also suggest using a library, such as `jQuery`, to make it easier. – Andreas Jun 25 '16 at 23:53
  • Some people willl argue that you should not send a POST instead of a GET if you want to have a RESTful API. In simple words: POST is only to create data, PUT is to update, GET is to retrieve data – jolumg Sep 19 '18 at 07:57
  • 4
    @jolumg The *some people* didn't read the [HTTP definition of the POST method](https://tools.ietf.org/html/rfc7231#section-4.3.3): *"The POST method requests that the target resource **process** the representation enclosed in the request according to the resource's **own specific semantics**"*. Sure, the most common semantic is for the resource to create something, but *process* is more generic and can mean other things, e.g. *run* a credit check using the supplied data. `GET` would be an inappropriate method for that. – Andreas Sep 19 '18 at 15:41
  • @Andreas do I need to create deserializer classes to convert nested JSON into Java objects? – likejudo Mar 13 '20 at 15:16
  • What if you want to pass multiple named complicated parameters? Such as @RequestBody (EntityOne, EntityTwo) – Devin Jul 09 '20 at 19:42
  • @Devin You mean like already shown in this answer below the **UPDATE** line? --- *FYI:* There can be only one `@RequestBody` parameter, so if you have multiple entities, then you need a parent object to contain them in that one-and-only object sent to the server. – Andreas Jul 09 '20 at 23:47
  • I mean to deserialize objects dynamically into multiple parameters. You would have to build an alternative to @RequestBody that had knowledge of the possible request types. Probably too much overhead and too much effort. I just went with the wrapper solution – Devin Jul 11 '20 at 18:31
39

you can pass multiple params in url like

http://localhost:2000/custom?brand=dell&limit=20&price=20000&sort=asc

and in order to get this query fields , you can use map like

    @RequestMapping(method = RequestMethod.GET, value = "/custom")
    public String controllerMethod(@RequestParam Map<String, String> customQuery) {

        System.out.println("customQuery = brand " + customQuery.containsKey("brand"));
        System.out.println("customQuery = limit " + customQuery.containsKey("limit"));
        System.out.println("customQuery = price " + customQuery.containsKey("price"));
        System.out.println("customQuery = other " + customQuery.containsKey("other"));
        System.out.println("customQuery = sort " + customQuery.containsKey("sort"));

        return customQuery.toString();
    }
Om Prakash Sharma
  • 1,682
  • 22
  • 13
  • 2
    This really helped me in creating a GET service with dynamic URL params. Thanks @Om Sharma – sunil Feb 01 '19 at 14:46
2

Multiple parameters can be given like below,

    @RequestMapping(value = "/mno/{objectKey}", method = RequestMethod.GET, produces = "application/json")
    public List<String> getBook(HttpServletRequest httpServletRequest, @PathVariable(name = "objectKey") String objectKey
      , @RequestParam(value = "id", defaultValue = "false")String id,@RequestParam(value = "name", defaultValue = "false") String name) throws Exception {
               //logic
}
0

Yes its possible to pass JSON object in URL

queryString = "{\"left\":\"" + params.get("left") + "}";
 httpRestTemplate.exchange(
                    Endpoint + "/A/B?query={queryString}",
                    HttpMethod.GET, entity, z.class, queryString);
techspl
  • 43
  • 5