(代表问题作者发布答案)。
步骤 1)如果您创建一个新控制器(我使用 grails create-controller <controller>,然后编辑生成的控制器以从 RestfulController<domain type> 扩展(但不要覆盖任何方法)。然后为您的控制器设置 URL 映射,在我的例子中这是
"/api/org"(resources:'OrgRoleInstance')
我的模型中有相应的域类“OrgRoleInstance”。
create-controller 操作还会生成一个空视图包“views/orgRoleInstance”(不生成 gson 文件)
a) 如果你现在运行应用程序并打开 url
http://localhost:8080/api/org
那么你仍然会得到一个呈现的响应(像这样)!
[{"id":1,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Service_Provider"},"name":"Vodafone","mags":[{"id":2}]},{"id":2,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Maintainer"},"name":"Cisco","mags":[{"id":1}]},{"id":3,"sites":[],"domains":[],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Supplier"},"name":"Cisco","mags":[]},{"id":4,"sites":[{"id":1},{"id":2}],"domains":[{"id":1}],"role":{"enumType":"com.softwood.domain.OrgRoleInstance$OrgRoleType","name":"Customer"},"name":"Acme","mags":[]}]
事实上,有一些“默认框架逻辑”试图呈现从 RestfulController 继承的“索引”(和“显示”等)动作的默认实现。即使没有预先存在的 gson,也可以这样做 - 不提供警告。
第 2 步:下一步停止应用(它仍在缓存之前的“默认”行为)。
现在转到空视图目录并创建一个像这样没有模型的“index.gson”
json ([1,2,3])
然后在您的 IDE 中重新启动应用程序。现在,当它启动时,它会检测到 index.gson 存在,当您调用 url 'http://localhost:8080/api/org' 时,您得到的是静态列表 [1,2,3] 的渲染 json
第 3 步:gson 视图在幕后使用静态编译,并且非常繁琐以完全正确。然而,在默认 RestfulController index action 的情况下,从域模型中选择一个 OrgRoleInstances 列表并作为 lit 传递给视图。如果您希望数据绑定到视图工作,那么如果您的域对象是类型 T,您会得到一个 List<T> 返回。
代码库中的内部默认设置是,如果您返回 List<T> 进行响应,则视图中的数据模型假定为 List<T> <T>List,即在我的示例中为
List<OrgRoleInstance> orgRoleInstanceList 在 gson 视图模型中。现在使用修改后的 index.gson(您可以在开发模式下不停止/启动服务器的情况下对其进行编辑)
import com.softwood.domain.OrgRoleInstance
model {
List<OrgRoleInstance> orgRoleInstanceList
}
json {
recordCount orgRoleInstanceList.size()
}
现在,当您获取 URL 时,您会得到一个包含列表大小的 json 响应:
{"recordCount":4}
请注意,如果您像这样向模型添加额外变量:
import com.softwood.domain.OrgRoleInstance
model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}
json {
recordCount orgRoleInstanceList.size()
size orgRoleInstanceCount
}
并修改 index.gson 以打印新的 Integer 变量 - 然后它不是来自默认响应操作的数据绑定。
浏览器响应如下所示:
{"recordCount":4,"size":null}
选项 4:-查看调用“模板”类。建立一个期望List<T> 的模型后,通过数据绑定构建的运行时类型是“grails.orm.PagedResultList”的一个实例。这是一个 Iterable 类型。
在文档中阅读这非常令人困惑 - 但是如果您创建一个名为 _<file>.gson 的文件,这真的不清楚。那么这个被处理的是一个模板gson文件。
这可以有自己的模型/json,但是因为所有这些都是静态编译的,所以你必须让类型完全匹配,并在调用模板时在必要时声明模型变量的“名称”(通过 g.render 或隐式tmpl.<file>。
当您从父视图调用模板时,您可以传递 List<T> 可迭代模型类型或在父视图中迭代并将每个 <T> 传递给模板。您必须确保您传递给 tmpl 的模型类型在 tmpl 模型中声明为相同的类型。
例如假设父视图中有一个List<T>,但模板中有一个<T>,您需要为列表中的每个项目调用tmpl。例如
如果你有一个像“_orgRoleInstance.gson”这样的tmpl。
如果你有这样的父视图(注意单个 <T> 声明和名为 'org' 的模型变量
import com.softwood.domain.OrgRoleInstance
model {
OrgRoleInstance org
}
json {
id org.id
name org.name
}
然后父视图“index.gson”你需要这样的东西,它调用 tmpl 的次数与列表中的条目一样多,但是我必须告诉框架 tmpl 模型变量名称是 'org ' 通过传递一张地图。这将按照您的预期呈现。
import com.softwood.domain.OrgRoleInstance
model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}
orgRoleInstanceList.each { OrgRoleInstance org ->
json tmpl.orgRoleInstance(org:org)
}
如果您将 tmpl 变量声明为“def org”,它仍然有效,但由于它是静态类型的,因此该变量作为 Object 的静态实例传递(运行时类型是正确的,但您不能只访问属性为静态类型是 Object),并且很难整理出访问属性所需的强制转换。
如果你想让父视图将模型List<T>变量传递给tmpl,你可以=但你必须确保tmpl中的模型变量是List<T>否则数据绑定不起作用。
现在您可以在模板中调用 json 并遍历 List
例如像这样修改 tmpl
import com.softwood.domain.OrgRoleInstance
model {
//OrgRoleInstance org
List<OrgRoleInstance> orgs
}
json {
id orgs.id
name orgs.name
}
和这样的修改后的父视图来调用 tmpl:
import com.softwood.domain.OrgRoleInstance
model {
List<OrgRoleInstance> orgRoleInstanceList
Integer orgRoleInstanceCount
}
/*
orgRoleInstanceList.each { OrgRoleInstance org ->
json tmpl.orgRoleInstance(orgs:org)
}*/
//alternate approach
json tmpl.orgRoleInstance (orgs:orgRoleInstanceList)
渲染的是这样的:
{"id":[1,2,3,4],"name":["Vodafone","Cisco","Cisco","Acme"]}
您会注意到有一个 json 子句,因此它首先迭代所有 id,然后迭代所有名称。
如果这不是您想要的,则必须遍历列表以依次执行每个操作
即像这样修改过的 tmpl 将依次遍历每个条目
import com.softwood.domain.OrgRoleInstance
model {
//OrgRoleInstance org
List<OrgRoleInstance> orgs
}
json (orgs) {OrgRoleInstance org ->
id org.id
name org.name
}
并在浏览器中生成它
[{"id":1,"name":"Vodafone"},{"id":2,"name":"Cisco"},{"id":3,"name":"Cisco"},{"id":4,"name":"Acme"}]
对于其他对 Grails 视图感到困惑的人,我希望这能说明这在 url 映射之间是如何工作的(您可以使用 Gradle“urlMappingsReport”来查看这些),并显示哪些 url 映射到哪些操作。然后,您需要创建与这些操作同名的 gson 视图,并配置您的 gson 视图和您创建的任何 tmpl,以了解 JsonViews 在处理您的代码时应用的隐式行为。