如何在Grails中实例化惰性列表?

如何在Grails中实例化惰性列表?,grails,Grails,我正在尝试将JSON数组接受到命令对象中。该数组如下所示: [ {prop1:'a', 'prop2:'b', prop3:'c'}, {prop1:'d', 'prop2:'e', prop3:'f'}, {prop1:'g', 'prop2:'h', prop3:'i'}, ... ] 我试图通过惰性列表接受数组 class MyCommand { List myList = ListUtils.lazyList([], FactoryUtils.instantiateFactor

我正在尝试将JSON数组接受到命令对象中。该数组如下所示:

[
{prop1:'a', 'prop2:'b', prop3:'c'},
{prop1:'d', 'prop2:'e', prop3:'f'},
{prop1:'g', 'prop2:'h', prop3:'i'},
...
]
我试图通过惰性列表接受数组

class MyCommand {
    List myList = ListUtils.lazyList([], FactoryUtils.instantiateFactory(Map))
}
但我得到了以下错误:

InstantiateFactory: The constructor must exist and be public . Stacktrace follows:
Message: InstantiateFactory: The constructor must exist and be public
    Line | Method
->>  113 | findConstructor    in org.apache.commons.collections.functors.InstantiateFactory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|     86 | <init>             in     ''
|     67 | getInstance . . .  in     ''
|    121 | instantiateFactory in org.apache.commons.collections.FactoryUtils

我应该使用另一种方法吗?

Map
是一个接口,因此不能实例化它。您需要选择要使用的具体类型,例如
HashMap
LinkedHashMap

您不需要在命令对象中使用惰性列表。您可以简化代码,让内置数据绑定系统惰性地初始化
列表

// grails-app/controllers/demo/DemoController.groovy
package demo

class DemoController {

    def demo(MyCommand co) {
        [command: co]
    }
}

class MyCommand {
    List<Map> data
}
当您这样做时,数据绑定系统将创建一个
MyCommand
的实例,它将初始化
data
属性,使其最初为空的
List
,然后用JSON中表示的所有
映射填充该
List

该代码位于的项目中。该项目包括以下通过的测试:

 // test/unit/demo/DemoControllerSpec.groovy
package demo

import grails.test.mixin.TestFor
import spock.lang.Specification


@TestFor(DemoController)
class DemoControllerSpec extends Specification {

    void "test binding a List of Map to a command object"() {
        when:
        request.method = 'POST'
        request.json = '''
            {"data": [
                      {"prop1":"a", "prop2":"b", "prop3":"c"},
                      {"prop1":"d", "prop2":"e", "prop3":"f"},
                      {"prop1":"g", "prop2":"h", "prop3":"i"}
                     ]
            }'''
        def model = controller.demo()
        def command = model.command

        then:
        command instanceof MyCommand
        command.data instanceof List
        command.data.size() == 3

        command.data[0] instanceof Map
        command.data[0].prop1 == 'a'
        command.data[0].prop2 == 'b'
        command.data[0].prop3 == 'c'

        command.data[1] instanceof Map
        command.data[1].prop1 == 'd'
        command.data[1].prop2 == 'e'
        command.data[1].prop3 == 'f'

        command.data[2] instanceof Map
        command.data[2].prop1 == 'g'
        command.data[2].prop2 == 'h'
        command.data[2].prop3 == 'i'
    }
}

List myList=[].withLazyDefault{[:]}
这会将整个列表加载到myList的第一项中:(您所做的编辑使它看起来像是将一个JSON字符串传递给
remoteFunction
,以获取
params
的值,而不是一个
Map
。看起来您可能想进行ajax调用,并将JSON作为调用的主体。我不认为
remoteFunction
的行为与您所认为的一样,但是其中一个问题与最初关于惰性列表的问题相去甚远。使用此方法将整个JSON数组加载到单个列表项中。如果我使用
JSON.parse(params.myList)
我每行有一个映射,但我更愿意使用惰性列表这是出于我的好奇心而提出的一个问题。它是否也会自动绑定一个类似于
列表的结构?
?在查看您的答案后,我也会尝试一下。您可以,有点。请看。如果您必须比类型更具体,您可以通过自定义绑定来实现这一点helper,它涉及更多的代码,但不是很多。谢谢。是的,对于类型,它不起作用。我必须在属性名称上使用binding helper和一些过滤逻辑,我想从列表列表中显式绑定。我将更多地使用它,如果可能的话,发布一个小应用。再次感谢:)但是,奇怪的行为是,如果我尝试在
FooCommand
内部绑定为
List
,我会遇到此错误。
消息:CreditCard约束只应用于字符串属性
不知从何而来。我在命令对象中没有任何信用卡字段。可能是默认为信用卡验证的错误仍然没有爱。pr我发送JSON的方式有问题吗?我使用的是
remoteFunction
。我将补充这个问题以使事情更清楚。
{"data": [
{prop1:'a', 'prop2:'b', prop3:'c'},
{prop1:'d', 'prop2:'e', prop3:'f'},
{prop1:'g', 'prop2:'h', prop3:'i'},
...
]}
 // test/unit/demo/DemoControllerSpec.groovy
package demo

import grails.test.mixin.TestFor
import spock.lang.Specification


@TestFor(DemoController)
class DemoControllerSpec extends Specification {

    void "test binding a List of Map to a command object"() {
        when:
        request.method = 'POST'
        request.json = '''
            {"data": [
                      {"prop1":"a", "prop2":"b", "prop3":"c"},
                      {"prop1":"d", "prop2":"e", "prop3":"f"},
                      {"prop1":"g", "prop2":"h", "prop3":"i"}
                     ]
            }'''
        def model = controller.demo()
        def command = model.command

        then:
        command instanceof MyCommand
        command.data instanceof List
        command.data.size() == 3

        command.data[0] instanceof Map
        command.data[0].prop1 == 'a'
        command.data[0].prop2 == 'b'
        command.data[0].prop3 == 'c'

        command.data[1] instanceof Map
        command.data[1].prop1 == 'd'
        command.data[1].prop2 == 'e'
        command.data[1].prop3 == 'f'

        command.data[2] instanceof Map
        command.data[2].prop1 == 'g'
        command.data[2].prop2 == 'h'
        command.data[2].prop3 == 'i'
    }
}