【问题标题】:Grails: Easy and efficient way to parse JSON from a RequestGrails:从请求中解析 JSON 的简单有效的方法
【发布时间】:2014-03-18 00:50:14
【问题描述】:

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

  • 我得到一个 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 对象是唯一的方法?

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

编辑:我现在获取 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 字符串。

【问题讨论】:

  • JSON 被视为 Map。因此,在您的情况下,您可以使用 map.key 从 json 中获取值,例如:json.loginName
  • 谢谢柏。但我的问题更多是关于“技术”或“工具”或“api”,这将使通过 JSON 解析生活变得更容易。

标签: json grails grails-plugin


【解决方案1】:

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

  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
}

命令如下所示:

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

它的“bindTo”方法是理解如何从传入请求中获取参数并将其映射到常规对象的关键逻辑部分。该对象的类型是“YourClass”,它看起来像这样:

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

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

jsonArray1.size()

应该是:

jsonArray.size()

以及基本修复:

def object1 = jsonArray[1]

应该

def object1 = jsonArray[0]  

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

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

【讨论】:

  • 在我消化你的解决方案之前给我几分钟。看起来肯定很有趣。谢谢。
  • 我想我最终会像你建议的那样使用命令对象的概念。谢谢。
  • 不错的选择,很高兴能帮上忙
  • 如果你还在看这个,我需要更多帮助。我现在将 JSON 作为字符串参数获取到控制器中。你能指导我如何使用 org.grails.codehaus API 中的 JSONArray 或 JSONObject 来解析 JSON 字符串吗?我面临 JSONArray[1] not found JSONExceptions etc etc.
  • 检查上面,我编辑了我原来的答案,所以这个评论保持可读
【解决方案2】:

我看到您的示例包含错误,这导致您实施更复杂的 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]

【讨论】:

    猜你喜欢
    • 2014-08-04
    • 2020-07-29
    • 2016-03-06
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 2018-02-17
    相关资源
    最近更新 更多