Issue with parsing nested JSON values with Lift-JSON

223 Views Asked by At

I'm using Scala 2.12 and trying to parse the below JSON file.

{
    "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
            }
        }
    }
}

I've loaded the json into config variable, defined a case class and trying the below:

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

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

This gives me the error 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

I can't use `operation1' and retrieve children as operations are random.

I need to retrieve the operation names operation1, operation2, operation4, .. and their respective aliases and weights. Any ideas?

1

There are 1 best solutions below

1
On BEST ANSWER

You are missing at least one level of nesting, and possibly also the implicit val formats.

This will print all of the operations. Note the conversion into JObject in order to be able to retrieve field names.

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

Output:

operation1:(activity_operation,10)
operation2:(service_operation,22)
operation1:(activity_operation,14)
operation4:(service_operation,16)