Grails:从请求中解析 JSON 的简单有效的方法

raj*_*adu 4 grails json grails-plugin

如果这是一个重复的问题,请原谅我。我已经完成了一些具有类似要求的问题/答案,但不知何故同时有点不知所措和困惑。我的要求是:

  • 我得到一个 JSON 字符串/对象作为请求参数。(例如:params.timesheetJSON)
  • 然后我必须解析/迭代它。

这是我的 grails 控制器将接收的 JSON:

{
    "loginName":"user1",
    "timesheetList":
    [
        {
            "periodBegin":"2014/10/12",
            "periodEnd":"2014/10/18",
            "timesheetRows":[
                {
                    "task":"Cleaning",
                    "description":"cleaning description",
                    "paycode":"payCode1"
                },
                {
                    "task":"painting",
                    "activityDescription":"painting description",
                    "paycode":"payCode2"
                }
            ]
        }
    ],
    "overallStatus":"SUCCESS"
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 如何从请求中检索整个 JSON 字符串?request.JSON 这里可以吗?如果是这样, request.JSON.timesheetJSON 会产生我想要的实际 JSON 作为 JSONObject 吗?

  2. 解析从请求中获取的 JSON 对象的最佳方法是什么?是 grails.converters.JSON 吗?或者还有其他简单的解析方法吗?就像某些 API 一样,它会通过自动处理解析将 JSON 作为对象集合返回。或者以编程方式解析 JSON 对象是唯一的方法吗?

就像我说的,如果问题听起来含糊不清,请原谅我。任何好的参考 JSON parsing with grails 在这里也可能会有帮助。

编辑:我现在获取 JSON 字符串的方式发生了变化。我获取 JSON 字符串作为请求参数。

String saveJSON // This holds the above JSON string.

def jsonObject = grails.converters.JSON.parse(saveJSON) // No problem here. Returns a JSONObject. I checked the class type.
def jsonArray = jsonArray.timesheetList // No problem here. Returns a JSONArray. I checked the class type.
println "*** Size of jsonArray1: " + jsonArray1.size() // Returns size 1. It seemed fine as the above JSON string had only one timesheet in timesheetList

def object1 = jsonArray[1] // This throws the JSONException, JSONArray[1] not found. I tried jsonArray.getJSONObject(1) and that throws the same exception.
Run Code Online (Sandbox Code Playgroud)

基本上,我现在希望无缝地迭代 JSON 字符串。

pap*_*ito 5

我写了一些代码来解释如何做到这一点,您可以在下面看到,但为了清楚起见,首先是您问题的答案:

  1. 上面写的 JSON 字符串将是发送到其余控制器的 POST 有效负载的内容。Grails 将使用其数据绑定机制将传入数据绑定到您应该准备的 Command 对象。它必须具有与 JSON 字符串中的参数相对应的字段(见下文)。将命令对象绑定到实际的域对象后,只需对字段和列表进行操作即可获取所需的所有数据

  2. 下面的示例显示了解析 JSON 对象的方法。传入的请求本质上是一个嵌套的映射,可以通过点简单地访问

现在一些代码说明了如何做到这一点。在您的控制器中创建一个接受“YourCommand”对象作为输入参数的方法:

def yourRestServiceMethod (YourCommand comm){
    YourClass yourClass = new YourClass()
    comm.bindTo(yourClass)

    // do something with yourClass
    // println yourClass.timeSheetList
}
Run Code Online (Sandbox Code Playgroud)

该命令如下所示:

class YourCommand {
    String loginName
    List<Map> timesheetList = []
    String overallStatus

    void bindTo(YourClass yourClass){
        yourClass.loginName=loginName
        yourClass.overallStatus=overallStatus
        timesheetList.each { sheet ->
            TimeSheet timeSheet = new TimeSheet()
            timeSheet.periodBegin = sheet.periodBegin
            timeSheet.periodEnd = sheet.periodEnd
            sheet.timesheetRows.each { row ->
                TimeSheetRow timeSheetRow = new TimeSheetRow()
                timeSheetRow.task = row.task
                timeSheetRow.description = row.description
                timeSheetRow.paycode = row.paycode
                timeSheet.timesheetRows.add(timeSheetRow)
            }

            yourClass.timeSheetList.add(timeSheet)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它的“bindTo”方法是理解如何从传入请求获取参数并将其映射到常规对象的关键逻辑。该对象的类型为“YourClass”,如下所示:

class YourClass {
    String loginName
    Collection<TimeSheet> timeSheetList = []
    String overallStatus
}
Run Code Online (Sandbox Code Playgroud)

属于该类的所有其他类:

class TimeSheet {
    String periodBegin
    String periodEnd
    Collection<TimeSheetRow> timesheetRows = []
}
Run Code Online (Sandbox Code Playgroud)

最后一个:

class TimeSheetRow {
    String task
    String description
    String paycode
}
Run Code Online (Sandbox Code Playgroud)

希望这个例子对您来说足够清楚并回答您的问题

编辑:根据新要求扩展答案

看看你的新代码,我发现你在写那篇文章时可能犯了一些拼写错误

def jsonArray = jsonArray.timesheetList
Run Code Online (Sandbox Code Playgroud)

应该:

def jsonArray = jsonObject.timesheetList
Run Code Online (Sandbox Code Playgroud)

但显然你在代码中正确地使用了它,否则它将无法工作,那么与“println”的那一行相同:

jsonArray1.size()
Run Code Online (Sandbox Code Playgroud)

应该是:

jsonArray.size()
Run Code Online (Sandbox Code Playgroud)

以及必要的修复:

def object1 = jsonArray[1]
Run Code Online (Sandbox Code Playgroud)

应该是

def object1 = jsonArray[0]  
Run Code Online (Sandbox Code Playgroud)

你的数组大小==1,索引从0开始。 // 有那么简单吗?;)

那么“object1”又是一个 JSONObject,因此您可以使用“.”访问字段。或者作为地图,例如这样:object1.get('periodEnd')