Spring rest api same url for bulk and single request

Viewed 383

I would like to have this API in a Spring boot app:

POST /items

{
  "name": "item1"
}

POST /items

[
  {
    "name": "item1"
  },
  {
    "name": "item2"
  },
]

So the same endpoint could accept array or a single element in a json body.

Unfortunatelly this doesn't work:

@PostMapping(path="items")
public ResponseEntity<String> items(@RequestBody  Item item) {}

@PostMapping(path="items")
public ResponseEntity<String> items(@RequestBody  List<Item> items) {}

I also tried this:

@PostMapping(path="items")
public ResponseEntity<String> items(@RequestBody @JsonFormat(with= JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) List<Item> items) {}

it doesn't work.

If I wrap the list like:

public class Items {
   @JsonFormat(with= JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 
   private List<item> items;
}

then unfortunately my request body would look like:

{
  "items": [
    {
      "name": "item1"
    },
    {
      "name": "item2"
    },
  ]
}

Do you know how I can have such API with spring boot?

1 Answers

You want a variable that can directly hold an Array or an Object. There is no straightforward way to achieve something like that because of the Static Typing restrictions of Java.

The only way I can imagine so far to achieve something like this is to create a single API that takes some generic type.

Like an Object:

@PostMapping(path="items")
public ResponseEntity<String> items(@RequestBody Object body) {
    if(body instanceof List) {
        
    } else {
        
    }
}

Or a String:

@PostMapping(path="items")
public ResponseEntity<String> items(@RequestBody String body) {
    if(body.charAt(0) == '[' && body.charAt(body.length() - 1) == ']') {
        
    } else if(body.charAt(0) == '{' && body.charAt(body.length() - 1) == '}') {
        
    } else {
        
    }
}

You'll have to do a lot of work manually.

Also, you can't create two APIs with the same path /items and the same method POST, they will raise a compile-time error.

Related