如何在 Grails 4 JSON 视图中将地图渲染为 属性
How to Render a Map as a property in a Grails 4 JSON View
我正在尝试渲染一个 JSON 视图,其中 属性 是 Map
。我希望它作为子对象在 JSON 中呈现。这看起来应该很容易,但我无法在任何地方找到它的记录。我创建了一个 example project on GitHub.
域名Class
class Breakfast {
String meat
String eggs
String side
}
控制器
class FooController {
static responseFormats = ['json', 'xml']
def index() {
Map<String, Breakfast> mealsByPerson = [
Tom: new Breakfast(meat: "bacon", eggs: "scrambled", side: "hashbrowns"),
Jack: new Breakfast(meat: "sausage", eggs: "over easy", side: "pancakes")
]
render template: "foo", model: [cost: 12.34f, date: new Date(), mealsByPerson: mealsByPerson]
}
}
/foo/_foo.gson
import rendermapexample.Breakfast
model {
Float cost
Date date
Map<String, Breakfast> mealsByPerson
}
json {
date date
cost cost
mealsByPerson mealsByPerson // HOW DO I RENDER THIS
}
这是我要渲染的JSON
{
"cost": 12.34,
"date": "2021-09-25T01:11:39Z",
"mealsByPerson": {
"Tom": {
"eggs": "scrambled",
"meat": "bacon",
"side": "hashbrowns"
},
"Jack": {
"eggs": "over easy",
"meat": "sausage",
"side": "pancakes"
}
}
}
这是我得到的错误
java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.grails.web.servlet.mvc.exceptions.ControllerExecutionException: Error rendering view: null
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.renderViewForTemplate(ResponseRenderer.groovy:617)
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.render(ResponseRenderer.groovy:353)
at rendermapexample.FooController.index(FooController.groovy:12)
... 15 common frames omitted
Caused by: grails.views.ViewRenderException: Error rendering view: null
at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:43)
at grails.views.mvc.GenericGroovyTemplateView.renderMergedOutputModel(GenericGroovyTemplateView.groovy:73)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:317)
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.renderViewForTemplate(ResponseRenderer.groovy:614)
... 17 common frames omitted
Caused by: java.lang.WhosebugError: null
at grails.plugin.json.converters.InstantJsonConverter.handles(InstantJsonConverter.groovy:18)
at grails.plugin.json.builder.DefaultJsonGenerator.findConverter(DefaultJsonGenerator.java:457)
at grails.plugin.json.builder.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:195)
at grails.plugin.json.builder.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:419)
...
我做不到:
下面的渲染语句在这个简单的例子中创建了我想要的 JSON,
但我的现实世界问题需要比 as JSON
提供的
更多的渲染控制
render ([cost: 12.34f, date: new Date(), mealsByPerson: mealsByPerson] as JSON)
示例项目
https://github.com/tonyerskine/rendermapexample
更新:
我在这里发布了一个相关问题以回应下面的评论:
您的 'BreakFast' class 中需要一个方法来导出到 JSON/XML/LinkedHashMap(或其他),它可以在对客户端的响应中作为字符串返回(即 getJson, getXml 等)
或者您需要在控制器中进行转换;我会建议您 class 中的方法,因为它更干净并且允许重复使用。
如果将 _foo.gson
更改为以下内容:
import rendermapexample.Breakfast
model {
Float cost
Date date
Map<String, Breakfast> mealsByPerson
}
json {
date date
cost cost
mealsByPerson g.render(mealsByPerson) {}
}
响应将包括以下内容:
{
"cost": 12.34,
"date": "2021-09-27T17:24:14Z",
"mealsByPerson": {
"Jack": {
"eggs": "over easy",
"meat": "sausage",
"side": "pancakes"
},
"Tom": {
"eggs": "scrambled",
"meat": "bacon",
"side": "hashbrowns"
}
}
我正在尝试渲染一个 JSON 视图,其中 属性 是 Map
。我希望它作为子对象在 JSON 中呈现。这看起来应该很容易,但我无法在任何地方找到它的记录。我创建了一个 example project on GitHub.
域名Class
class Breakfast {
String meat
String eggs
String side
}
控制器
class FooController {
static responseFormats = ['json', 'xml']
def index() {
Map<String, Breakfast> mealsByPerson = [
Tom: new Breakfast(meat: "bacon", eggs: "scrambled", side: "hashbrowns"),
Jack: new Breakfast(meat: "sausage", eggs: "over easy", side: "pancakes")
]
render template: "foo", model: [cost: 12.34f, date: new Date(), mealsByPerson: mealsByPerson]
}
}
/foo/_foo.gson
import rendermapexample.Breakfast
model {
Float cost
Date date
Map<String, Breakfast> mealsByPerson
}
json {
date date
cost cost
mealsByPerson mealsByPerson // HOW DO I RENDER THIS
}
这是我要渲染的JSON
{
"cost": 12.34,
"date": "2021-09-25T01:11:39Z",
"mealsByPerson": {
"Tom": {
"eggs": "scrambled",
"meat": "bacon",
"side": "hashbrowns"
},
"Jack": {
"eggs": "over easy",
"meat": "sausage",
"side": "pancakes"
}
}
}
这是我得到的错误
java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.grails.web.servlet.mvc.exceptions.ControllerExecutionException: Error rendering view: null
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.renderViewForTemplate(ResponseRenderer.groovy:617)
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.render(ResponseRenderer.groovy:353)
at rendermapexample.FooController.index(FooController.groovy:12)
... 15 common frames omitted
Caused by: grails.views.ViewRenderException: Error rendering view: null
at grails.views.AbstractWritableScript.writeTo(AbstractWritableScript.groovy:43)
at grails.views.mvc.GenericGroovyTemplateView.renderMergedOutputModel(GenericGroovyTemplateView.groovy:73)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:317)
at grails.artefact.controller.support.ResponseRenderer$Trait$Helper.renderViewForTemplate(ResponseRenderer.groovy:614)
... 17 common frames omitted
Caused by: java.lang.WhosebugError: null
at grails.plugin.json.converters.InstantJsonConverter.handles(InstantJsonConverter.groovy:18)
at grails.plugin.json.builder.DefaultJsonGenerator.findConverter(DefaultJsonGenerator.java:457)
at grails.plugin.json.builder.DefaultJsonGenerator.writeObject(DefaultJsonGenerator.java:195)
at grails.plugin.json.builder.DefaultJsonGenerator.writeMapEntry(DefaultJsonGenerator.java:419)
...
我做不到:
下面的渲染语句在这个简单的例子中创建了我想要的 JSON,
但我的现实世界问题需要比 as JSON
提供的
render ([cost: 12.34f, date: new Date(), mealsByPerson: mealsByPerson] as JSON)
示例项目
https://github.com/tonyerskine/rendermapexample
更新:
我在这里发布了一个相关问题以回应下面的评论:
您的 'BreakFast' class 中需要一个方法来导出到 JSON/XML/LinkedHashMap(或其他),它可以在对客户端的响应中作为字符串返回(即 getJson, getXml 等)
或者您需要在控制器中进行转换;我会建议您 class 中的方法,因为它更干净并且允许重复使用。
如果将 _foo.gson
更改为以下内容:
import rendermapexample.Breakfast
model {
Float cost
Date date
Map<String, Breakfast> mealsByPerson
}
json {
date date
cost cost
mealsByPerson g.render(mealsByPerson) {}
}
响应将包括以下内容:
{
"cost": 12.34,
"date": "2021-09-27T17:24:14Z",
"mealsByPerson": {
"Jack": {
"eggs": "over easy",
"meat": "sausage",
"side": "pancakes"
},
"Tom": {
"eggs": "scrambled",
"meat": "bacon",
"side": "hashbrowns"
}
}