如何在Grails中实例化惰性列表?
我正在尝试将JSON数组接受到命令对象中。该数组如下所示:如何在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
[
{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'
}
}