从JSON中提取嵌套实体和值

时间:2014-06-29 15:43:54

标签: json scala jira lift case-class

我正在尝试从Jira中提取问题并将它们放入List [Issue]。 我想出了如何下载和解析JSON:

val json = JsonParser.parse(content)

我还可以在JSON的根目录中提取一些数字:

val total = (json \ "total").extract[Int]
val maxResults = (json \ "maxResults").extract[Int]
println("Received " + total + " from " + maxResults + " issues")

但是当我试图提取所有问题的清单时

val issues = (json \ "issues")
println(issues)
issues.extract[List[Issue]]

我收到错误消息: 线程“main”中的异常net.liftweb.json.MappingException:id没有可用值 不知道如何将JString(13604)转换为int 我不明白为什么它不能将13604转换为Int。 这是我的案例类:

case class Issue(id: Int,
    key: String,
    summary: String,
    issueTypeName: String,
    resolutionName: Option[String],
    resolutionDate: Option[DateTime],
    timeSpent: Option[Int],
    creatorName: String,
    reporterName: String,
    updated: DateTime,
    created: DateTime,
    priorityName: String,
    description: String,
    dueDate: Option[DateTime],
    statusName: String,
    assigneeName: String,
    projectId: Int,
    projectKey: String,
    projectName: String,
    timeEstimate: Option[Int],
    ownerName: String,
    timeOriginalEstimate: Option[Int]
                    )
  1. 有人可以帮我解决这个问题吗?

  2. 此外,JSON具有某些属性的嵌套元素,例如project具有嵌套的id,key和name。在我使用json \ "issues"提取问题之前,我看到了另一个错误 - 我相信这是因为JSON提取器不知道他需要转到嵌套元素。 我怎么能让他知道呢? 我以为我可以这样做:

    for(issue< - issues){   val id =(issue \“id”)。extract [Int]   的println(ID) }

  3. 使用issue \ "project" \ "id"作为嵌套项,然后创建新的Case Class对象并将其添加到List var(可变但我不知道如何以其他方式执行)。但我收到编译时错误:

     Error:(53, 16) value foreach is not a member of net.liftweb.json.JsonAST.JValue
            for(issue <- issues) {
                         ^
    

    我是Scala和整个Java基础架构和框架的新手,所以我很感激代码示例。


    PS。当我在我的case类中将id更改为String时,我现在收到另一个错误:

    Exception in thread "main" net.liftweb.json.MappingException: No usable value for summary Did not find value which can be converted into java.lang.String
    

    这是因为“summary”嵌套在“fields”中。所以,我的第二个问题仍然是实际的: 2.如何使用嵌套值?

    和新的相关问题: 3.如果我想使用Int作为id - 我该如何转换它?

2 个答案:

答案 0 :(得分:4)

那是因为json中的id字段以字符串形式出现(“id”:“10230”https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Query+issues),liftjson会自动转换为JString。在您的case类中,您需要将id字段设为String。

2)用例类来处理嵌套的json。如果你有一个看起来像这样的json

{
  "id": "10230",
  "fields": {
    "summary": "testing"
  }
}

你需要两个案例类

case class Issues(
   id: String,
   fields: Summary
)

case class Summary(
   summary: String
)

3)我认为你不能在extract方法中转换为Int,因为JSON结构将它定义为String。提取值后,必须进行转换。

答案 1 :(得分:2)

我自己找到了解决方案:

val issues = (json \\ "issues").children
 for (issue <- issues) {
        val item = new Issue (
                    (issue \ "id").extract[String].toInt,
                    (issue \ "fields" \ "summary").extract[String],
                    (issue \ "fields" \ "issuetype" \ "name").extract[String],
                    (issue \ "fields" \ "resolutiondate").extractOrNone[String] match {
                        case None => None
                        case Some (null) => None
                        case Some (dt) => Some (dateTimeFormatter.withZoneUTC ().parseDateTime (dt))
                    },
        etc...) 
}

在这种情况下,我继续使用单个案例类(我为自己的需要定义的结构)并将嵌套的json属性解析到它中,在需要的时候进行类型转换。