Grails JSON 数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2671711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Grails JSON array
提问by armandino
I'm converting a list of Foo objects to a JSON string. I need to parse the JSON string back into a list of Foos. However in the following example, parsing gives me a list of JSONObjects instead of Foos.
我正在将 Foo 对象列表转换为 JSON 字符串。我需要将 JSON 字符串解析回 Foos 列表。但是在下面的例子中,解析给了我一个 JSONObjects 而不是 Foos 的列表。
Example
例子
List list = [new Foo("first"), new Foo("second")]
def jsonString = (list as JSON).toString()
List parsedList = JSON.parse(jsonString) as List
println parsedList[0].getClass() // org.codehaus.groovy.grails.web.json.JSONObject
How can I parse it into Foos instead? Thanks in advance.
我怎样才能把它解析成 Foos 呢?提前致谢。
回答by Dónal
I had a look at the API docs for JSON and there doesn't appear to be any way to parse to a JSON string to a specific type of object.
我查看了 JSON 的 API 文档,似乎没有任何方法可以将 JSON 字符串解析为特定类型的对象。
So you'll just have to write the code yourself to convert each JSONObjectto a Foo. Something like this should work:
因此,您只需自己编写代码即可将每个代码转换JSONObject为Foo. 这样的事情应该工作:
import grails.converters.JSON
import org.codehaus.groovy.grails.web.json.*
class Foo {
def name
Foo(name) {
this.name = name
}
String toString() {
name
}
}
List list = [new Foo("first"), new Foo("second")]
def jsonString = (list as JSON).toString()
List parsedList = JSON.parse(jsonString)
// Convert from a list of JSONObject to a list of Foo
def foos = parsedList.collect {JSONObject jsonObject ->
new Foo(name: jsonObject.get("name"))
}
A more general solution would be to add a new static parsemethod such as the following to the JSONmetaClass, that tries to parse the JSON string to a List of objects of a particular type:
更通用的解决方案是向元类添加一个新的静态parse方法,例如以下内容JSON,该方法尝试将 JSON 字符串解析为特定类型的对象列表:
import grails.converters.JSON
import org.codehaus.groovy.grails.web.json.*
class Foo {
def name
Foo(name) {
this.name = name
}
String toString() {
name
}
}
List list = [new Foo("first"), new Foo("second")]
def jsonString = (list as JSON).toString()
List parsedList = JSON.parse(jsonString)
// Define the new method
JSON.metaClass.static.parse = {String json, Class clazz ->
List jsonObjs = JSON.parse(json)
jsonObjs.collect {JSONObject jsonObj ->
// If the user hasn't provided a targetClass read the 'class' proprerty in the JSON to figure out which type to convert to
def targetClass = clazz ?: jsonObj.get('class') as Class
def targetInstance = targetClass.newInstance()
// Set the properties of targetInstance
jsonObj.entrySet().each {entry ->
if (entry.key != "class") {
targetInstance."$entry.key" = entry.value
}
}
targetInstance
}
}
// Try the new parse method
List<Foo> foos = JSON.parse(jsonString, Foo)
// Confirm it worked
assert foos.every {Foo foo -> foo.class == Foo && foo.name in ['first', 'second'] }
You can try out the code above in the groovy console. A few warnings
您可以在 groovy 控制台中尝试上面的代码。一些警告
- I have only performed very limited testing on the code above
- There are two JSON classes in the latest Grails release, I'm assuming you're using the one that is not deprecated
- 我只对上面的代码进行了非常有限的测试
- 最新的 Grails 版本中有两个 JSON 类,我假设您使用的是未弃用的类
回答by jondow
If you are doing this in a Grails controller, and Foo IS indeed a domain object, don't forget that armed with your JSON map, you can also do:
如果您在 Grails 控制器中执行此操作,并且 Foo 确实是一个域对象,请不要忘记使用您的 JSON 映射,您还可以执行以下操作:
List list = [new Foo("first"), new Foo("second")]
def jsonString = (list as JSON).toString()
List parsedList = JSON.parse(jsonString) as List
Foo foo = new Foo()
bindData(foo, parsedList[0]);
回答by Sandman
I've taken this code and extended it to work with nested structures. It relies on a 'class' attribute existing in the JSON. If there's a better way by now in Grails please let me know.
我已经使用了这段代码并将其扩展为使用嵌套结构。它依赖于 JSON 中存在的“类”属性。如果现在 Grails 中有更好的方法,请告诉我。
// The default JSON parser just creates generic JSON objects. If there are nested
// JSON arrays they are not converted to theirs types but are left as JSON objects
// This converts nested JSON structures into their types.
// IT RELIES ON A PROPERTY 'class' that must exist in the JSON tags
JSON.metaClass.static.parseJSONToTyped = {def jsonObjects ->
def typedObjects = jsonObjects.collect {JSONObject jsonObject ->
if(!jsonObject.has("class")){
throw new Exception("JSON parsing failed due to the 'class' attribute missing: " + jsonObject)
}
def targetClass = grailsApplication.classLoader.loadClass(jsonObject.get("class"))
def targetInstance = targetClass.newInstance()
// Set the properties of targetInstance
jsonObject.entrySet().each {entry ->
// If the entry is an array then recurse
if(entry.value instanceof org.codehaus.groovy.grails.web.json.JSONArray){
def typedSubObjects = parseJSONToTyped(entry.value)
targetInstance."$entry.key" = typedSubObjects
}
else if (entry.key != "class") {
targetInstance."$entry.key" = entry.value
}
}
targetInstance
}
return typedObjects
}
回答by EpicVoyage
As of Grails 2.5, this is possible:
从 Grails 2.5 开始,这是可能的:
Period test = new Period()
test.periodText = 'test'
String j = test as JSON
def p = JSON.parse(j)
test = p.asType(Period)
println(test.periodText)
Output:
输出:
test
I am unsure of when it became an option.
我不确定它何时成为一种选择。

