从JSON中提取嵌套实体和值

时间:2021-09-09 00:54:48

I am trying to extract Issues from Jira and put them into List[Issue]. I figured out how to download and parse JSON:

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

val json = JsonParser.parse(content)

I can also extract some numbers in the root of JSON:

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

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

But when I am trying to extract list of all the issues

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

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

I am receiving a error: Exception in thread "main" net.liftweb.json.MappingException: No usable value for id Do not know how to convert JString(13604) into int I don't understand why can't it convert 13604 to Int. Here is my case class:

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

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. Can someone help me with this Int problem?

    有人可以帮我解决这个Int问题吗?

  2. Moreover, JSON has nested elements for some properties like project has nested id, key and name. Before I extracted issues with json \ "issues" I saw another error - I believe it is because JSON extractor don't know he need to go to the nested elements. How can I let him know about it? I thought I could do something like this:

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

    for(issue <- issues) { val id = (issue \ "id").extract[Int] println(id) }

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

And use issue \ "project" \ "id" for nested items, and then create new Case Class object and add it to List var (mutable but I have no idea how to do it in other way). But I receive compile time error:

并对嵌套项使用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) {
                     ^

I am new to Scala and overall Java infrastructure and frameworks, so I would appreciate for samples of code.

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


PS. When I changed id to String in my case class I now receive another error:

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

This is because "summary" is nested into the "fields". So, my second question is still actual: 2. How can I work with nested values?

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

and new related question: 3. If I want to use Int for id - how can I convert it?

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

2 个解决方案

#1


4  

That's because the id field in the json comes in as a string ("id": "10230" https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Query+issues ), which liftjson automatically converts to a JString. In your case class you need to make the id field a String.

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

2) use case classes to deal with nested json. If you have a json that looks like this

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

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

you will need two case classes

你需要两个案例类

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

case class Summary(
   summary: String
)

3) I don't think you can convert to Int in the extract method because the JSON structure defines it as a String. The conversion will have to happen after you extract the value.

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

#2


2  

I have found solution myself:

我自己找到了解决方案:

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

In this case I continue using single case class (the structure I define for my own needs) and parse nested json properties into it, doing types transformations on the fly where needed.

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

#1


4  

That's because the id field in the json comes in as a string ("id": "10230" https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Query+issues ), which liftjson automatically converts to a JString. In your case class you need to make the id field a String.

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

2) use case classes to deal with nested json. If you have a json that looks like this

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

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

you will need two case classes

你需要两个案例类

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

case class Summary(
   summary: String
)

3) I don't think you can convert to Int in the extract method because the JSON structure defines it as a String. The conversion will have to happen after you extract the value.

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

#2


2  

I have found solution myself:

我自己找到了解决方案:

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

In this case I continue using single case class (the structure I define for my own needs) and parse nested json properties into it, doing types transformations on the fly where needed.

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