Извлечение вложенных сущностей и значений из JSON

Я пытаюсь извлечь задачи из Jira и поместить их в список [проблема]. Я понял, как скачать и разобрать 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: нет полезного значения для идентификатора. Не знаю, как преобразовать 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. Может ли кто-нибудь помочь мне с этой проблемой Int?

  2. Кроме того, в JSON есть вложенные элементы для некоторых свойств, таких как проект, в котором есть вложенные идентификатор, ключ и имя. Прежде чем я извлек проблемы с json \ "issues", я увидел еще одну ошибку - я полагаю, что это связано с тем, что экстрактор JSON не знает, что ему нужно перейти к вложенным элементам. Как я могу сообщить ему об этом? Я думал, что могу сделать что-то вроде этого:

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

И используйте issue \ "project" \ "id" для вложенных элементов, а затем создайте новый объект класса Case и добавьте его в List var (изменяемый, но я понятия не имею, как это сделать по-другому). Но я получаю ошибку времени компиляции:

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

Я новичок в Scala и общей инфраструктуре и фреймворках Java, поэтому буду признателен за примеры кода.


PS. Когда я изменил id на String в своем классе case, я теперь получаю еще одну ошибку:

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

Это потому, что «сводка» вложена в «поля». Итак, мой второй вопрос все еще актуален: 2. Как я могу работать с вложенными значениями?

и новый связанный вопрос: 3. Если я хочу использовать Int для id - как я могу его преобразовать?


person Konstantin Trunin    schedule 29.06.2014    source источник


Ответы (2)


Это потому, что поле id в json представлено в виде строки ("id": "10230" https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Query+issues ), который liftjson автоматически преобразует в JString. В вашем классе case вам нужно сделать поле id строкой.

2) использовать классы case для работы с вложенным json. Если у вас есть JSON, который выглядит так

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

вам понадобятся два класса case

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

case class Summary(
   summary: String
)

3) Я не думаю, что вы можете преобразовать в Int в методе извлечения, потому что структура JSON определяет его как строку. Преобразование должно произойти после извлечения значения.

person p3lagic    schedule 29.06.2014
comment
Спасибо за ответ - полезно. Однако теперь я получаю сообщение об ошибке: Исключение в потоке main. 1. Как работать с вложенными значениями? 2. Если мне нужно использовать Int для id - как я могу его преобразовать? - person Konstantin Trunin; 29.06.2014
comment
@KonstantinTrunin Получили ли вы решение проблемы, которую вы упомянули в комментарии выше? ТИА - person texens; 09.06.2015

Я сам нашел решение:

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

В этом случае я продолжаю использовать класс single case (структуру, которую я определяю для своих нужд) и анализировать в нем вложенные свойства json, выполняя преобразования типов на лету, где это необходимо.

person Konstantin Trunin    schedule 04.07.2014