Grails JSON数组

arm*_*ino 11 grails groovy json

我正在将Foo对象列表转换为JSON字符串.我需要将JSON字符串解析回Foos列表.但是在下面的示例中,解析为我提供了JSONObjects而不是Foos的列表.

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
Run Code Online (Sandbox Code Playgroud)

我怎样才能把它解析成Foos呢?提前致谢.

Dón*_*nal 13

我查看了JSON的API文档,似乎没有任何方法可以将JSON字符串解析为特定类型的对象.

因此,您只需自己编写代码即可将每个代码转换JSONObjectFoo.这样的事情应该有效:

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"))
}
Run Code Online (Sandbox Code Playgroud)

更通用的解决方案是向metaClass 添加一个新的静态parse方法,例如以下方法JSON,它尝试将JSON字符串解析为特定类型的对象List:

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'] }
Run Code Online (Sandbox Code Playgroud)

您可以在groovy控制台中试用上面的代码.一些警告

  • 我只对上面的代码进行了非常有限的测试
  • 最新的Grails版本中有两个JSON类,我假设您使用的是未弃用的类