skip to Main Content

I’m running into an issue I don’t know how to resolve. I need to return a JSON object that has duplicate keys.

I understand this is perfectly valid according to the JSON specification. See ecma-404, page 6 that reads:

The JSON syntax does not impose any restrictions on
the strings used as names, does not require that name strings be unique…

I need to return this:

{
  "id":"1401",
  "sku":"C18-25",
  "sku":"A15-70"
}

I’ve been using a typical rest method in Spring Boot:

@GetMapping("/{id}")
@ResponseBody
public ResponseEntity<?> getProduct(@PathVariable String id) {
  Map<String, String> r = new HashMap<>();
  r.put("id", "1401");
  r.put("sku", "C18-25");
  r.put("sku", "A15-70");
  return new ResponseEntity<Map<String, String>>(r, HttpStatus.OK);
}

But it only keeps the last entry:

{
  "id":"1401",
  "sku":"A15-70"
}

How can I return multiple entries with the same name?

4

Answers


  1. A HashMap only allows unique key values, so there is no way for you to use HashMap for this purpose. Also while you are correct, you can use duplicate key values in a JSON body, it is not recommended. Why not make sku an array like this?

    "sku":["A15-70","C18-25"]
    
    Login or Signup to reply.
  2. While creating map create like this

    Map<String, List<String>> map = new HashMap<>();
    

    while putting existing key in Map check using containsKey() method and put duplicate value in List of key

    you will get result like this

    { "id":"1401", "sku":["A15-70","C18-25"] }

    Login or Signup to reply.
  3. You can just return a string with response entity.

    String response = "{n"+
    "  "id":"1401",n"+
    "  "sku":"C18-25",n"+
    "  "sku":"A15-70"n"+
    "}";
    return new ResponseEntity<String>(response, HttpStatus.OK);
    

    It is not pretty, but it is supported by Spring and will get the job done.

    Login or Signup to reply.
  4. Here’s how you can construct a JSON-object from an arbitrary number of Map.Entry instances (but obviously if JSON structure would be more complex it’ll be better to avoid generating it manually at all costs since it would be tedious and error-prone):

    @SafeVarargs
    public static String entriesToJson(Map.Entry<String, String>... entries) {
        
        return Arrays.stream(entries)
            .map(e -> "t"%s" : "%s"".formatted(e.getKey(), e.getValue()))
            .collect(Collectors.joining(",n", "{n", "n}"));
    }
    
    @GetMapping("/{id}")
    @ResponseBody
    public ResponseEntity<?> getProduct(@PathVariable String id) {
        // your logic
        return ResponseEntity.ok(
            entriesToJson(
                Map.entry("id", "1401"),
                Map.entry("sku", "C18-25"),
                Map.entry("sku", "A15-70")
            )
        );
    }
    

    Usage example:

    public static void main(String[] args) {
        System.out.println(entriesToJson(
            Map.entry("id", "1401"),
            Map.entry("sku", "C18-25"),
            Map.entry("sku", "A15-70")
        ));
    }
    

    Output:

    {
        "id" : "1401",
        "sku" : "C18-25",
        "sku" : "A15-70"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search