Grails绑定集合枚举

时间:2011-08-27 17:52:45

标签: data-binding grails spring-mvc groovy enums

在我的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自动执行请求参数 - &gt;基于枚举名称的枚举转换。只是它没有,我尝试定义一个执行此转换的属性编辑器:

class RelationshipStatusEnumEditor extends PropertyEditorSupport {    

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

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

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

2 个答案:

答案 0 :(得分:1)

使用Grails 2.3中引入的数据透辑表,我提出了以下解决方案,用于将请求参数转换为枚举集合。例如,给定这些枚举

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
    }
}

然后在EnumCollectionConverter中将resources.groovy注册为Spring bean - 您为bean选择的名称无关紧要。然后使用上面的类将逗号分隔的字符串转换为num集合,使用

注释相关属性
class MyCommand {
    @BindingFormat('Gender')
    Collection<Gender> genders

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

传递给@BindingFormat的值应该是将存储在绑定集合中的枚举类型的简单名称。

答案 1 :(得分:0)

据我所知,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