简体   繁体   中英

Passing JSON objects in a REST HTTP GET request using Spring MVC

According to this REST model and to what I think is a consensus on REST: every REST retrieval should be performed as a HTTP GET request. The problem now is how to treat complex JSON objects as parameters in GET requests with Spring MVC. There is also another consensus I found saying "use POST for retrievals!" just because "the big companies do this!", but I have been asked to try to stick to the "REST level 2 rules".

First question: am I trying to do something that make sense?

I want to send via GET requests arrays / lists / sets of JSON objects, in Java with Spring MVC. I can not figure out what's wrong with my attempts, I have tried to add/remove double quotes, played around with the URL parameters, but I can not achieve this goal.

What's wrong with the following code? The code snippet is coming from a MVC controller.

@RequestMapping(
        value = "/parseJsonDataStructures",
        params = {
                "language",
                "jsonBeanObject"

        }, method = RequestMethod.GET, headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public HttpEntity<ParsedRequestOutputObject> parseJsonDataStructures(

        @RequestParam String language,
        @RequestParam CustomJsonBeanObject[] customJsonBeanObjects){

    try {
        ParsedRequestOutputObject responseFullData = customJsonBeanObjectService.parseJsonDataStructures(customJsonBeanObjects, language);

        return new ResponseEntity<>(responseFullData, HttpStatus.OK);
    } catch (Exception e) {
        // TODO
    }
}

I've tried multiple ways to build the URL request (always getting HTTP code 400 Bad Request), this is an example:

http://[...]/parseJsonDataStructures?language=en&jsonBeanObject={"doubleObject":10, "enumObject":"enumContent", "stringObject":"stringContent"}

The JSON object variables ar of type:

  • Double (not the primitive)
  • enum
  • String

I am assuming I can pass multiple jsonBeanObject parameters one after the other.

The jsonBeanObject Java bean is:

public class CustomJsonBeanObject {

    private Double doubleObject;
    private CustomEnum enumObject;
    private String stringObject;

    /**
     * Factory method with validated input.
     *
     * @param doubleObject
     * @param enumObject
     * @param stringObject
     * @return
     */
    public static CustomJsonBeanObject getNewValidatedInstance(Double doubleObject, CustomEnum enumObject, String stringObject) {
        return new CustomJsonBeanObject
                (
                        doubleObject ,
                        enumObject   ,
                        stringObject
                );
    }

    private CustomJsonBeanObject(Double doubleObject, CustomEnum enumObject, String stringObject) {
        this.doubleObject = doubleObject;
        this.enumObject = enumObject;
        this.stringObject = stringObject;
    }


    public CustomJsonBeanObject() {}

    // getter setter stuff

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}

First create a request bean which should encapsulate the parameters you expect as part of request. Will call it as SomeRequest

Second in the controller use @RequestBody instead of @RequestParam

@ResponseBody public HttpEntity<ParsedRequestOutputObject> parseJsonDataStructures(@RequestBody SomeRequest someRequest) { ... }

Third use RestTemplate as client to invoke your REST services. Sample code below -

SomeRequest someRequest = new SomeRequest();
// set the properties on someRequest
Map<String, String> userService = new HashMap<String, String>();
RestTemplate rest = new RestTemplate();
String url = endPoint + "/parseJsonDataStructures";
ResponseEntity<SomeResponse> response = rest.getForEntity(url, someRequest,
      SomeResponse.class, userService);
SomeResponse resp = response.getBody();

Your statement about only using GET or POST is for REST completely incorrect. The HTTP method used depends on the action you are performing. For retrieval, you are supposed to use a GET, for add/create a POST, for remove/delete a DELETE, and for replace a PUT. Also, to be "true" REST you should only change state through self-documented actions provided by the server response (read up on HATEOAS ). Most people don't do the latter.

As an aside, I tried searching for "REST level 2" and also got nothing by sites about beds and Dungeons'and'Dragons. I have personally never heard of it, so it is apparently so new that there are not a lot of sites talking about it or it may be called something else.

To your point about how to send a JSON object, Spring MVC can handle that out-of-the-box. You can read up on it here , which uses the @RequestBody to pull in the entire HTTP request body then parses it using your JSON processor of choice. There are plenty of code samples there describing how to handle lists and such.

package com.lightaria.json;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
public class StatusController {

@RequestMapping("/lkg.latest")
public MainStatus stat() throws IOException{
    byte[] jsonData = Files.readAllBytes(Paths.get("/home/admin/StatusPage/Downloads/JSON/lkg-latest.json"));
    ObjectMapper objectMapper =new ObjectMapper();
    MainStatus stat1 = objectMapper.readValue(jsonData, MainStatus.class);
    System.out.println("Status\n"+stat1);
    return stat1;
}
}

I have used the above method to parse a JSON file and store it as JSON object. One can easily replace the path by a URL. Hope it helps.

Don't forget to make a application.properties file consisting port and various other configs. for ex - (to run the RESTful application on port 8090, the application.properties file should have server.port=8090 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM