How to Pass a List and a Separate String Using @Requestbody in Springboot

Spring RequestBody with either List<Object> or Object. Name for both are same "data"

EDIT

You can create DTOs for your inputs but receive the @RequestBody as a JSON string and then parse it as a list or a single object request.

DTO for a request list:

public class InputDataList {

private List<Input> data;

// getters and setters
}

DTO for a single request object:

public class InputDataSingle {

private Input data;

// getters and setters
}

Then on your controller:

        @PostMapping(path="/path")
public @ResponseBody String getSomething(@RequestBody String json){

// this is better done in a service but for simplicity, I write it in the controller
try {
InputDataSingle data = new ObjectMapper().readValue(json, InputDataSingle.class);
// If fails to parse as a single object, parse as a list
} catch (Exception) (
InputDataList data = new ObjectMapper().readValue(json, InputDataList.class);
}
// handle objects in the service layer
}

Is it possible to split request params in Spring controllers?

Yes, you can certainly do that, you're almost there.

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> participants(@RequestParam("sort") List<String> sort) {

//...
}

You should now be able to call your service like this (if search is located at your root, otherwise adapt according to your situation):

curl "localhost:8080/search?sort=sortField1&sort=sortField2&sort=sortField3"

Hope this helps!

EDIT
Sorry, I have read your comments and what you need is clear to me now. I have created a workaround for you that is almost what you want I think.

So first a SortParams class:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortParams {
private List<SortParam> sortParamList;

public SortParams(String commaSeparatedString) {
sortParamList = Arrays.stream(commaSeparatedString.split(","))
.map(p -> SortParam.valueOf(p))
.collect(Collectors.toList());
}

public List<SortParam> getSortParamList() {
return this.sortParamList;
}

public enum SortParam {
FOO, BAR, FOOBAR;
}
}

Then your controller could look like this:

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<List<SortParams.SortParam>> search(@RequestParam("sort") SortParams sort) {
return ResponseEntity.ok(sort.getSortParamList());
}

Now your SortParams object has a list of SortParam:

curl "localhost:8080/search?sort=FOO,BAR"

["FOO","BAR"]

Would something like this fit what you're looking for?

SpringBoot: Using @RequestParam and @RequestBody together

The problem was the content encoding of the incoming request. Changing the curl command to

curl -H "Content-Type: application/json" -d '{ "name": "Joe Bloggs" }' http://localhost:8080/test?debug=Y

Resulted in my output showing

debug=N
json={ "name": "Joe Bloggs" }

How to accept RequestBody of different class types dynamically

You could do this by passing the JSON as a String into your controller method and then mapping this to whichever object you expect to need:

@PostMapping(value = "/myservice/{type}")
public ResponseEntity<?> myServiceApi(@PathVariable String type,
@RequestBody String somereq) {
ObjectMapper mapper = new ObjectMapper();
if (<something that indicates SomeClass1>) {
SomeClass1 someClass1 = mapper.readValue(somereq, SomeClass1.class);
} else if (<something that indicates SomeClass2>) {
SomeClass2 someClass2 = mapper.readValue(somereq, SomeClass2.class);
}
}

Although to be honest if you really are expecting bodies with completely different structures my advice would be to just make separate API calls for these.

Do I need a separate object for every @RequestBody in Spring Boot

  1. Create a new entity if you will persist or operate on it

  2. If you need a custom view for existing entity (add/remove fields) DTO with custom serialization can be used

  3. There maybe a case when you don't want to create DTO because you will not reuse it anywhere, but need some quick solution for custom response you can use Map<String, Object> - the key will be used for JSON field name, and Object is for the value, for example:

    @RequestMapping(method = RequestMethod.POST)
    public Map<String, Object> login(@RequestParam Integer p1) {
    Map<String, Object> map = new HashMap<>();
    map.put("p1", p1);
    map.put("somethingElse", "456");
    return map;
    }

JSON response:

{
"p1": p1value,
"somethingElse": "456"
}

3rd case will suite you if you're not building too complex bodies with nested objects which should be customized based on some conditions. Use 2nd option in the opposite case.

@RequestBody, sending in List<String> in POST request

"tags": [{"Tag 1"}, {"Tag 2"}]

correspond to an array of object, not an array of String that should be represented like :

"tags": ["Tag 1", "Tag 2"]

Either change the client side to send an array of String : "tags": ["Tag 1", "Tag 2"].

Otherwise, change the client side and the backend side to declare a List that is parameterized with a custom class that will contain the String value.

Json to send :

"tags": [{"value": "Tag 1"}, {"value": "Tag 2"}]

mapping in the back end :

private List<MyObject> tags;

Where MyObject could be declared :

public class MyObject{
private String value;
... // getter - setter
}


Related Topics



Leave a reply



Submit