1

I want to write a REST Service which will except Key Values as follows:

LCD      Samsung
MOUSE    HP
MOUSE    Dell
DRINK    COKE
DRINK    PEPSI
LCD      DELL
LCD      APPLE
KEYBOARD Lenovo

What is the best format for accepting. If the users send as JSON then how can i read that in to a

List<String, List<String>>

or into Guava multi map.

Here is the sample JSON

{
    "LCD": "Samsung",
    "MOUSE": "HP", 
    "MOUSE": "DELL",
    "LCD": "Apple",
    "LCD": "DELL",
    "DRINK": "Coke",
    "LCD": "Lenovo",
    "DRINK": "Pepsi",
    "KEYBOARD": "Lenovo"
}

1 Answers1

1

Although it isn't an invalid thing to have duplicate keys in a JSON, it is not recommended. Refer to this question and specifically this answer which quotes the RFC which recommends why to not have duplicates.

Given this, there a bit of a cumbersome way to add the entries into the Multimap. The below codes assumes that the Json object you get is in the single line String format. If not, it isn't difficult to convert into one (careful with the newlines, the code below doesnt take care of that).

    String jsonStr = new String("{\"LCD\": \"Samsung\",\"MOUSE\": \"HP\",\"MOUSE\": \"DELL\",\"LCD\": \"Apple\",\"LCD\": \"DELL\",\"DRINK\": \"Coke\",\"LCD\": \"Lenovo\",\"DRINK\": \"Pepsi\",\"KEYBOARD\": \"Lenovo\"}");

    // Removing the first and last braces
    jsonStr = jsonStr.substring(1, jsonStr.length() - 1);

    // Create a Guava Multimap
    Multimap<String, String> myMap = ArrayListMultimap.create();

    // Split on comma for each key-value pair
    for(String item: jsonStr.split(",")) {
        // Get the individual key-value pair
        String[] keyValue = item.split(":");

        // Get the values between the the inverted commas
        String key = keyValue[0].substring(keyValue[0].indexOf("\"") + 1, keyValue[0].lastIndexOf("\""));
        String value = keyValue[1].substring(keyValue[1].indexOf("\"") + 1, keyValue[1].lastIndexOf("\""));

        // Add to map
        myMap.put(key, value);
    }

    // Print to check
    for(Map.Entry<String, String> entry: myMap.entries()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }

This isn't the best way to achieve the outcome, but given the nature of the input JSON there isn't much that can be done, since most of the JSON parsers (Gson, Jackson) dont take care of the duplicates. The above code will give the following output (the final print statement for checking the entries)

DRINK: Coke
DRINK: Pepsi
MOUSE: HP
MOUSE: DELL
KEYBOARD: Lenovo
LCD: Samsung
LCD: Apple
LCD: DELL
LCD: Lenovo

Note that the order isn't (cannot be) maintained by this map.

Community
  • 1
  • 1
Some guy
  • 1,210
  • 1
  • 17
  • 39
  • Thanks, this is definitely one way of doing this. I was thinking of some better way of doing this. but as you mentioned none of the json libraries are handling duplicate keys, tried some of them. Will try few more just so that i don't have to do this string manipulation. Also **do you think accepting the string as XML will make more sense here** ? The input has to be consumed by a rest service and further processing needs to be done. Any thoughts ? And yes you can also print as myMap.asMap(); – Sonali Kapoor Nov 14 '15 at 13:00
  • If it were to me, I would convert the json being sent as a json array. With that, each key-value pair will be a JsonObject. If this is the case, then you can use any of the popular Json parsers to read each of those objects and then add it to your Multimap. – Some guy Nov 15 '15 at 09:44