user3497321
user3497321

Reputation: 523

Issue with parsing nested JSON values with Lift-JSON

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?

Upvotes: 0

Views: 220

Answers (1)

ELinda
ELinda

Reputation: 2821

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)

Upvotes: 0

Related Questions