How to create form in Spring MVC that allows to choose item from menu and it's quantity?

Solution 1:

It would be better if you could send DishQuantityMap in id to count format, something like Map<Integer, Integer>. Having some custom object as key in the map can be problematic both for frontend and backend sides. Still if you have to do it like that, it is possible.

OrderDto class - as in your example, don't forget getters and setters.

I'll assume Dish class looks something like this:

public class Dish {


  private Long id;
  private String name;
  private String description;

  //default constructor, getters and setters
  //since it is a key in a map you need proper overrides of hashCode() and equals()
}

I'll also assume you are using Jackson for serialization/deserialization. Jackson cannot just deserialize you custom objects into keys, so you need to create and register KeyDeserializer for your Dish. For example like this:

public class DishKeyDeserializer extends KeyDeserializer {

  private static final ObjectMapper MAPPER = new ObjectMapper();

  @Override
  public Object deserializeKey(String key, DeserializationContext context) throws IOException {
    return MAPPER.readValue(key, Dish.class);
  }
}

Here i am using another mapper to make deserialization of the string key easier. You can see how to register the deserializer in the example.

Your working json will look like this:

{
  "userEmail": "[email protected]",
  "userName": "username",
  "dishQuantityMap": {
    "{\"id\":2,\"name\":\"food2\",\"description\":\"yummiest\"}": 19,
    "{\"id\":1,\"name\":\"food1\",\"description\":\"yummy\"}": 11
  }
}

Take a note how key in the map is Dish object turned into json string, with proper escapes of quotes.

And an example to play around:

    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    //add key deserializer in module
    module.addKeyDeserializer(Dish.class, new DishKeyDeserializer());
    //register module
    mapper.registerModule(module);

    //getting the json as project resource, you get it however you need
    InputStream stream = ClassLoader.getSystemResourceAsStream("order.json");
    OrderDto parsedOrder = mapper.readValue(stream, OrderDto.class);