0

I have a Json from which I want to pick List of List Json, where instance can be multiple inside List. Using json-path easily we can pick if giving index number of List/Array. But in a Big File we don't know total how many instance will be there and we have not to loose any data. So number of instance has to be check in a dynamic way and pick seperate json for all inside List node. Additionally has to create relation_path also for all the Data.

Can Anyone suggest How to check if a json node is Array/List (Ex : 2 Drive) and how many nested List objects are available like 2 Partition in 1st Drive and 1 Partition in 2nd Drive. These numbers are not fixed to be provide in json-path code.

Input List of List Json :

{"Start":{"HInfo":{"InfoId":"650FEC74","Revision":"5.2.0.51","Drive":[{"InfoId":"650FEC74","Index":0,"Name":"Drive0","Partition":[{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":0},{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":1}]},{"InfoId":"650FEC74","Index":1,"Name":"Drive1","Partition":{"InfoId":"650FEC74","DriveID":"3F275869","Index":0}}]}}}

Output List of Json :

[{"Partition":[{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":0},{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":1}],"relation_tree":"Start/HInfo/Drive/Drive-1/Partition"},{"Partition":{"InfoId":"650FEC74","DriveID":"3F275869","Index":0},"relation_tree":"Start/HInfo/Drive/Drive-2/Partition"}]

What I am trying using json-path, but this is not fittable as I here I am providing Index Number manually, which is not possible in all the case as index number can be 0 to any.

val jsonString = """{"Start":{"HInfo":{"InfoId":"650FEC74","Revision":"5.2.0.51","Drive":[{"InfoId":"650FEC74","Index":0,"Name":"Drive0","Partition":[{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":0},{"InfoId":"650FEC74","DriveID":"F91B1F36","Index":1}]},{"InfoId":"650FEC74","Index":1,"Name":"Drive1","Partition":{"InfoId":"650FEC74","DriveID":"3F275869","Index":0}}]}}}"""
  val jsonStr: JsValue = Json.parse(jsonString)
    var pruneJson1 = (__ \ "Partition").json.copyFrom((__ \ "Start" \ "HInfo" \ "Drive" \ (0) \ "Partition").json.pick)
    val finalPartitionPrune1 = Option(jsonStr.transform(pruneJson1)).get.get.as[JsObject] + ("relation_tree" -> Json.toJson("Start"+"/"+"HInfo"+"/"+"Drive"+"/"+"Drive-1"+"/"+"Partition"))

    println(finalPartitionPrune1)

  var pruneJson2 = (__ \ "Partition").json.copyFrom((__ \ "Start" \ "HInfo" \ "Drive" \ (1) \ "Partition").json.pick)
  val finalPartitionPrune2 = Option(jsonStr.transform(pruneJson2)).get.get.as[JsObject] + ("relation_tree" -> Json.toJson("Start"+"/"+"HInfo"+"/"+"Drive"+"/"+"Drive-2"+"/"+"Partition"))

   println(finalPartitionPrune2)

1 Answers1

0

This is the simplest solution I could think of:

val finalJson = Json.toJson(
  (jsonStr \ "Start" \ "HInfo" \ "Drive")
    .as[Seq[JsValue]]
    .map(jsValue => JsObject(Seq(
      "Partition" -> (jsValue \ "Partition").get,
      "relation_tree" -> JsString(s"Start/HInfo/Drive/Drive-${(jsValue \ "Index").get}/Partition")))))

Basically it reads all drives as sequence of JsValues and then maps them to JsObjects with needed format. It uses Index value of drive to create relation_tree value, so it will fail if this value is missing. As an alternative you can use zipWithIndex method to add your own indices to sequence. As a final step it converts sequence back to JsValue

Here's zipWithIndex version:

val finalJson =   Json.toJson(
  (jsonStr \ "Start" \ "HInfo" \ "Drive")
    .as[Seq[JsValue]]
    .zipWithIndex
    .map{ case (jsValue, index) => JsObject(Seq(
      "Partition" -> (jsValue \ "Partition").get,
      "relation_tree" -> JsString(s"Start/HInfo/Drive/Drive-$index/Partition")))
    })
Smerk
  • 166
  • 1
  • 4
  • Hi @Smerk, Thanks.. its working fine but as you mentioned it will fail if "Index" is unavailable inside json. I tried with zipWithIndex but not getting. If you don't mind can you please syntax with zipWithIndex? Please. – Anamika Singh Jul 18 '20 at 10:46
  • Sure, I edited my answer to include zipWithIndex version – Smerk Jul 20 '20 at 08:17
  • Hi @Smerk, Thank You. Just to test I removed Index from json to check that if this field is not in json, code is working fine or not but resulted with this Error : Exception in thread "main" java.util.NoSuchElementException: None.get. looks like still this is depends upon "Index" field. – Anamika Singh Jul 20 '20 at 09:36
  • Are you sure you didn't remove more than just indices. That error should only appear if "Partition" field is missing. I removed all "Index" fields from input and it still worked fine – Smerk Jul 20 '20 at 10:07
  • Sorry @Smerk.. This was my mistake. Actually your previous solution was still in IDE and that was failing due to missing "Index". This new version is working fine without field "Index" too. Thank You – Anamika Singh Jul 20 '20 at 10:44