Проблема с анализом вложенных значений JSON с помощью Lift-JSON

Я использую Scala 2.12 и пытаюсь проанализировать приведенный ниже файл JSON.

{
    "comp1": {
        "metrics": {
            "operation1": {
                "alias": "activity_operation",
                "weight": 10
            },
            "operation2": {
                "alias": "service_operation",
                "weight": 22
            }
        }
    },
    "comp2": {
        "metrics": {
            "operation1": {
                "alias": "activity_operation",
                "weight": 14
            },
            "operation4": {
                "alias": "service_operation",
                "weight": 16
            }
        }
    }
}

Я загрузил json в переменную конфигурации, определил класс case и попробовал следующее:

  case class OperationDetails(alias: String, weight: Int)

  for (detail <- (config \ "comp1").children) {
    println(detail.extract[OperationDetails])
  }

Это дает мне ошибку Exception in thread "main" net.liftweb.json.MappingException: No usable value for alias. Did not find value which can be converted into java.lang.String

Я не могу использовать `operation1' и извлекать дочерние элементы, так как операции случайны.

Мне нужно получить имена операций operation1, operation2, operation4, .. и их соответствующие псевдонимы и веса. Любые идеи?


person user3497321    schedule 24.07.2020    source источник


Ответы (1)


Вам не хватает как минимум одного уровня вложенности и, возможно, неявного значения formats.

Это напечатает все операции. Обратите внимание на преобразование в JObject, чтобы можно было получить имена полей.

  // Setup 
  case class Operation(alias: String, weight: Int)
  implicit val formats = DefaultFormats

  // Traversal
  val comps: List[JsonAST.JValue] = config.children
  for (comp <- comps) {
    val metrics:List[JsonAST.JValue] = comp.children
    for (metric <- metrics) {
      val operations:List[JsonAST.JField] = metric.asInstanceOf[JObject].obj
      for (operation <- operations) {
        val op = operation.value.extract[Operation]
        // Do something here
        println(s"${operation.name}:(${op.alias},${op.weight})")
      }
    }
  }

Выход:

operation1:(activity_operation,10)
operation2:(service_operation,22)
operation1:(activity_operation,14)
operation4:(service_operation,16)
person ELinda    schedule 25.07.2020
comment
Спасибо. Это сработало как шарм. Я попытался преобразовать JSON в Map с помощью asInstanceOf[JObject].values и получить оттуда значения, но это выглядело не очень элегантно. - person user3497321; 26.07.2020