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

时间:2014-03-18 00:50:15

标签: json grails 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"
}

问题:

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

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

  3. 就像我说的那样,如果这个问题听起来很模糊,请原谅我。任何好的引用JSON解析与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.
    

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

2 个答案:

答案 0 :(得分:4)

我已经写了一些代码来解释如何做到这一点,你可以在下面看到,但要清楚,首先要回答你的问题:

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

  2. 通过JSON对象解析的方法如下面的示例所示。进入请求实际上是一个嵌套的地图,只需用点来访问

  3. 现在有一些代码说明了如何做到这一点。 在你的控制器中创建一个接受"你的命令" object作为输入参数:

    def yourRestServiceMethod (YourCommand comm){
        YourClass yourClass = new YourClass()
        comm.bindTo(yourClass)
    
        // do something with yourClass
        // println yourClass.timeSheetList
    }
    

    命令如下所示:

    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)
            }
        }
    }
    

    它&#34; bindTo&#34; method是理解如何从incomming请求获取参数并将其映射到常规对象的关键逻辑。该对象属于&#34; YourClass&#34;它看起来像这样:

    class YourClass {
        String loginName
        Collection<TimeSheet> timeSheetList = []
        String overallStatus
    }
    

    属于该类的所有其他类:

    class TimeSheet {
        String periodBegin
        String periodEnd
        Collection<TimeSheetRow> timesheetRows = []
    }
    

    和最后一个:

    class TimeSheetRow {
        String task
        String description
        String paycode
    }
    

    希望这个例子足够清楚并回答你的问题

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

    看看你的新代码,我发现你在写这篇文章时可能会做一些拼写错误

    def jsonArray = jsonArray.timesheetList
    

    应该是:

    def jsonArray = jsonObject.timesheetList
    

    但你显然在你的代码中已正确使用它,否则它将无法正常工作,那么与&#34; println&#34;的那一行相同:

    jsonArray1.size()
    

    shuold be:

    jsonArray.size()
    

    和基本修复:

    def object1 = jsonArray[1]
    

    shuold be

    def object1 = jsonArray[0]  
    

    你的数组大小== 1,索引从0开始.//它可以那么容易吗? ;)

    然后&#34; object1&#34;又是一个JSONObject,因此您可以使用&#34;。&#34;来访问这些字段。或者作为地图,例如:     object1.get(&#39; periodEnd&#39)

答案 1 :(得分:0)

我看到您的示例包含错误,导致您实施更复杂的JSON解析解决方案。 我将您的示例重写为工作版本。 (至少现在是针对Grails 3.x)

String saveJSON // This holds the above JSON string.

def jsonObject = grails.converters.JSON.parse(saveJSON) 
println jsonObject.timesheetList // output timesheetList structure

println jsonObject.timesheetList[0].timesheetRows[1] // output second element of timesheetRows array: [paycode:payCode2, task:painting, activityDescription:painting description]