Grails的绑定集合枚举

问题描述:

在我的Grails应用程序,我有这样的枚举:Grails的绑定集合枚举

public enum RelationshipStatus{ 

    Single_Never_Married, 
    Separated, 
    Divorced, 
    Widowed; 
} 

我定义这个命令对象:

class MyCommand { 
    List<RelationshipStatus> relationshipStatuses 
} 

,我在我的控制器动作

一个使用
def myAction = {MyCommand myCommand -> 
} 

当我提交一个请求到这个动作的参数

user.relationshipStatuses=Separated&user.relationshipStatuses=Divorced 

我预计myCommand.relationshipStatuses将包含RelationshipStatus.SeparatedRelationshipStatus.Divorced,但实际上它是空的。

我的理解是,Grails根据枚举的名称自动执行请求参数 - >枚举转换。只要将它区分它不,我试图定义一个属性编辑器,做这种转换:

class RelationshipStatusEnumEditor extends PropertyEditorSupport {  

    public String getAsText() { 
     value.name() 
    } 

    public void setAsText(String text) { 
     RelationshipStatus.valueOf(text) 
    } 
} 

我注册这个编辑器使用Grails/Spring和再次尝试,但结果是一样的。是否可以将请求参数绑定到Enum的Collection

+0

我相信,Grails不知道如何填充你的列表,因为它放弃了列表类型(List )上的信息。我不确定,如果可能的话。 – sbglasius

使用Grails的2.3引入了DataBinder的,我想出了以下解决方案转换请求参数来收集的枚举。例如,考虑到这些枚举

enum Gender { 
    MALE, FEMALE 
} 

enum Season { 
    SPRING, SUMMER, AUTUMN, WINTER 
} 

和该命令对象

class MyCommand { 
    Collection<Gender> genders 
    Collection<Season> seasons 
} 

,我们假定我们要转换为字符串像"MALE,FEMALE""SPRING,SUMMER,WINTER"到相应的枚举集合。首先,提供FormattedValueConverter的实现,确实

class EnumCollectionConverter implements FormattedValueConverter { 

    /** 
    * To make other enums bindable, just add them to this list 
    */ 
    private static final List<Class<Enum>> convertableEnums = [Gender, Season] 

    @Override 
    Object convert(value, String format) { 

     Class<Enum> targetEnumClass = convertableEnums.find { it.simpleName == format } 

     if (targetEnumClass) { 
      List<String> enumConstantNames = value.toString().tokenize(',') 
      return enumConstantNames.collect { targetEnumClass.valueOf(it) } 
     } 
     value 
    } 

    @Override 
    Class<?> getTargetType() { 

     // this class converts to a Collection<T extends Enum<T>> but the return value 
     // of this method can't be any more specific than Collection due to type erasure 
     Collection 
    } 
} 

然后注册EnumCollectionConverterresources.groovy一个Spring bean转换 - 没关系什么名字,你选择这个bean。然后使用类以上用逗号分隔的字符串转换为NUM集合,

class MyCommand { 
    @BindingFormat('Gender') 
    Collection<Gender> genders 

    @BindingFormat('Season') 
    Collection<Season> seasons 
} 

注释相关属性传递给@BindingFormat值应该是将存储在枚举类型的简单名称绑定的集合。

正如我所知,如果它是空的,默认情况下grails不会填充List属性。只有它已经存在,并且项目的索引被传递。

尝试定义这个属性为:

import org.apache.commons.collections.ListUtils 
import org.apache.commons.collections.Factory 

class MyCommand { 
    List<RelationshipStatus> relationshipStatuses = ListUtils.lazyList([],{new RelationshipStatus()} as Factory) 
} 

,并提交参数为:

user.relationshipStatuses[0]=Separated&user.relationshipStatuses[1]=Divorced