简体   繁体   中英

Converting JSON to Enum type with @RequestBody

I have a master enum class which is essentially a class definition for a type of object. For example it looks something like the example below:

public enum ColorDefinition
{
     private String abbrev;
     private String color;
     private Class colorClass;
     RED("RD", "Red", Red.class),
     GREEN("GN", "Green", Green.class),
     BLUE("BL", "Blue", Blue.class)....
}

I am trying to set up a post request from a Javascript model, that sends a mapping in the body such as
{Red : 255, Green : 0, Blue: 0}

To a spring controlled endpoint that uses

@RequestMapping(value = "v1/color/EnableColors", method = RequestMethod.POST)
@ResponseBody
public ResponseObject enableColors(@RequestBody Map<ColorDefinition, Integer> colorMapping)

To which I get the following error message:
Can not construct Map key of type ColorDefinition from String "Red": not a valid representation: Can not construct Map key of type ColorDefinition from String "Red": not one of values for Enum class

What am I doing wrong here? Do I need some other method in the enum class to properly convert the incoming enum value? Should it be using another value from the enum (I have tried them with no success)? Any help is appreciated, it seems like this should be possible to automatically convert the incoming values, I just can't figure it out!

The error message explains what is going wrong: there is no definition for Red inside ColorDefinition . The case needs to match; enum values are case-sensitive. The keys in your JSON need to be RED , GREEN , and BLUE .

Internally, Spring uses valueOf to get the enum representation of the String. During deserialization, ColorDefinition.valueOf("Red") will throw an IllegalArgumentException because there is no definition for Red in ColorDefinition . This exception is intercepted by Spring, and this is why you see an error message. However, ColorDefinition.valueOf("RED") will return ColorDefinition.RED because there is a definition for RED in ColorDefinition .

If you need to handle mixed-case (Red), you can do something like this:

  public static class MyConverter extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
      setValue(ColorDefinition.valueOf(text.toUpperCase()));
    }    
  }

  @InitBinder
  public void initBinder(WebDataBinder binder)
  {
    binder.registerCustomEditor(ColorDefinition.class, new MyConverter ());
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM