Grails bind request parameters to enum

后端 未结 2 1526
暖寄归人
暖寄归人 2021-02-05 22:20

My Grails application has a large number of enums that look like this:

public enum Rating {
    BEST(\"be\"), GOOD(\"go\"), AVERAGE(\"av\"), BAD(\"ba\"), WORST(\         


        
相关标签:
2条回答
  • 2021-02-05 22:40

    So the default Databinding binds on the Enum name and not a separately defined property of the Enum. You can either create your own PropertyEditor as you have mentioned or do a work-around similar to this:

    class MyCommand {
     String ratingId
        Rating getRating() {
         return Rating.getEnumFromId(this.ratingId)
        }
        static constraints = {
         ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null })
        }
    }
    
    0 讨论(0)
  • 2021-02-05 23:02

    I found a solution I'm pretty happy with.

    Step 1: Create an implementation of PropertyEditorSupport to convert text to/from the relevant Enum

    public class EnumEditor extends PropertyEditorSupport {
    
        private Class<? extends Enum<?>> clazz
    
        public EnumEditor(Class<? extends Enum<?>> clazz) {
            this.clazz = clazz
        }
    
        public String getAsText() {
            return value?.id
        }
    
        public void setAsText(String text) {
            value = clazz.getEnumFromId(text)
        }
    }
    

    Step 2: Define a class that registers EnumEditor as a converter for the various enum classes. To change the list of enum classes that are bindable by id, just modify BINDABLE_ENUMS

    public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
    
        private static final String REQUIRED_METHOD_NAME = 'getEnumFromId'
    
        // Add any enums that you want to bind to by ID into this list
        private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2]
    
        public void registerCustomEditors(PropertyEditorRegistry registry) {            
    
            BINDABLE_ENUMS.each {enumClass ->
                registerEnum(registry, enumClass)
            }
        }
    
        /**
         * Register an enum to be bound by ID from a request parameter
         * @param registry Registry of types eligible for data binding
         * @param enumClass Class of the enum
         */
        private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) {
    
            boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method ->
                method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1
            }
    
            if (!hasRequiredMethod) {
                throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray())
            }
            registry.registerCustomEditor(enumClass, new EnumEditor(enumClass))
        }
    }
    

    Step 3: Make Spring aware of the registry above by defining the following Spring bean in grails-app/conf/spring/resources.grooovy

    customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
    
    0 讨论(0)
提交回复
热议问题