Parsing dynamic json data into scala object

1,298 views
Skip to first unread message

SMART Channel

unread,
Jan 30, 2015, 11:08:14 AM1/30/15
to scala...@googlegroups.com
Hi All,

I am using json library of playframework.

Dynamic json data

   "ruleCriteria": {
                  "left": {
                                 // statements
                         },
                  "conditionalOperator": "AND",
                  "right": {
                                     " left": {
                                                    //statements
                                                },
                                              "conditionalOperator": "AND",
                                              "right": {
                                                                "left": {
                                                                                 //statements
                                                                           },
                                                                         "conditionalOperator": "AND",
                                                                    "right": {
                                                                                    //statements
                         
                                                                                }
                                                       }
                               }
               }


I will be getting this data dynamically in json format. In this data, there can be one left condition(left, conditional operator, right) inside another(recursive in nature). It will be dynamic.
I want to parse this dynamic data and map it to scala object. 

Is there any way to parse this dynamic data?

Please somebody help me.

Thanks,
Jitendra

Oliver Ruebenacker

unread,
Jan 30, 2015, 11:32:18 AM1/30/15
to SMART Channel, scala-user

     Hello,

  Have you seen the Play tutorial on JSON basics?

     Best, Oliver

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Solutions Architect at Altisource Labs
Be always grateful, but never satisfied.

jitendra shelar

unread,
Jan 30, 2015, 12:33:10 PM1/30/15
to scala...@googlegroups.com
Hi Oliver,

Thanks for reply.

Yes, I went through the docs. I tried using "reads"  for parsing json data. But, it is only for static json data.
I also tried traversing json tree using '/' and '//'. But, I am not able to read the dynamic json data.
In my example in this post, there can be one left condition(left, conditional operator, right) inside another (recursive in nature).

Is there any way to parse such dynamic json data?

Regards,
Jitendra

Michel Daviot

unread,
Jan 30, 2015, 1:23:42 PM1/30/15
to jitendra shelar, scala...@googlegroups.com

Have you tried rapture json for play?


Oliver Ruebenacker

unread,
Jan 30, 2015, 1:23:47 PM1/30/15
to jitendra shelar, scala-user

     Hello,

  I'm not sure what you mean by "dynamic". You do seem to have a pre-defined structure. Reads can work recursively.

  You can use JsPath.readNullable for optional fields and it will give you an Option.

  You can put an if-clause or any logic you like into a Reads.read method, e.g.

  implicit val aReads = new Reads[A] {
    def reads(json: JsValue) : JsResult[A] = {
      ...
      if(...) {
        ...
      } else {
        ...
      }
    }
  }

  You can first read some fields and then decide how to proceed.

     Best, Oliver

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

jitendra shelar

unread,
Jan 30, 2015, 2:53:34 PM1/30/15
to scala...@googlegroups.com
Thanks Michel. Will check this library.

Thanks Oliver for your suggestions.
Dynamic, I mean,  recursive form of data ( left, conditionalOperator, right).
This recursive form can be of any type like below.
 
Eg 1:
  "ruleCriteria": {
                  "left": {
                                  "left": {
                                                   //statements
                                              },
                                    "conditionalOperator": "AND",
                                     "right": {
                                                    //statements
                                                  }
                         },
                  "conditionalOperator": "AND",
                  "right": {
                                         //statements
                               }
               }

 Eg2:
 "ruleCriteria": {
                  "left": {
                                 // statements
                         },
                  "conditionalOperator": "AND",
                  "right": {
                                  //statements
                               }
               }

Eg3:
  "ruleCriteria": {
                  "left": {
                                 // statements
                         },
                  "conditionalOperator": "AND",
                  "right": {
                                     " left": {
                                                    //statements
                                                },
                                              "conditionalOperator": "AND",
                                              "right": {
                                                                //statements
                                                       }
                               }
               }




For example, I may get data in either Eg1 or Eg2 or Eg3 or similar format. They willI be recursive in nature. 
How to parse such kind of json data?


On Friday, January 30, 2015 at 9:38:14 PM UTC+5:30, jitendra shelar wrote:

Jon Pretty

unread,
Feb 6, 2015, 5:30:43 AM2/6/15
to jitendra shelar, scala-user
Hi Jitendra,

I previously thought this was quite difficult to do, but I discovered you can extract recursively using Rapture JSON very easily, but you need to define the extractor for the recursive type manually.

Say we have a recursively-defined `Rule` type which looks like this:

  sealed trait Rule
  case class Expr(left: Rule, conditionalOperator: String, right: Rule) extends Rule​
​  case class ​Stats(stats: String)

Rapture will automatically generate extractors for case classes, based on their parameter names and types corresponding to JSON objects. ​I've made the example a bit simpler by assuming that a `Stats` branch can be identified by the presence of a `stats` key in the object.​

Given a JSON value in Rapture, `json`, we can attempt to extract a value from it like this:

  json.as[SomeType]

but there's no default extractor for the `Rule` type, so we have to define one.

We do this by composing the automatically-defined extractors for `Expr` and `Stats`, like this:

  implicit def ext: Extractor[Rule, Json] = Json.extractor[Stats] orElse Json.extractor[Expr]

What this is saying is: "in order to extract a `Rule`, first try to extract a `Stats`, and if that fails try to extract an `Expr`".

There are a couple of things to note about this. Firstly, the order is important: if you try `Expr` then `Stats`, you'll get infinite recursion. Secondly, the automatically-derived extractor for `Expr` can only be generated if it can find extractors corresponding to all of `Expr`'s parameter types, which includes `Rule`. So the extractor it finds is `ext` itself. It's recursive. You therefore need to make sure that `ext` is a `def` and not a `val` (normally `val` would be fine), and that it has an explicit type ascription, for the usual recursion reasons.

Other than that, you should then be able to write:

  json.as[Rule]

Cheers,
Jon

P.S. Thanks Michel for the Rapture JSON plug!

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Jon Pretty | @propensive

Oliver Ruebenacker

unread,
Feb 6, 2015, 8:01:09 AM2/6/15
to Jon Pretty, jitendra shelar, scala-user

     Hello,

  As I said earlier, Play can do JSON recursively, e.g.:

import play.api.libs.json.Reads
import play.api.libs.json.JsPath
import play.api.libs.functional.syntax._

object JsonTest extends App {

  case class TreeNode(left: Option[TreeNode], right: Option[TreeNode])

  implicit val treeNodeReads: Reads[TreeNode] =
    ((JsPath \ "left").readNullable[TreeNode] and (JsPath \ "right").readNullable[TreeNode])(TreeNode(_, _))

}

  If parser combinators like above don't work for your structure, you can also implement a Reads[TreeNode] more explicitly, which allows you to insert any additional logic (implicit reference to treeNodeReads does not work here, that's why we have (this) in two places):

  implicit val treeNodeReads = new Reads[TreeNode] {
    def reads(json: JsValue): JsResult[TreeNode] = {
      ((JsPath \ "left").readNullable[TreeNode](this) and (JsPath \ "left").readNullable[TreeNode](this))(TreeNode(_, _)).reads(json)
    }
  }


     Best, Oliver

Jitendra Shelar

unread,
Feb 6, 2015, 11:36:41 PM2/6/15
to Oliver Ruebenacker, Jon Pretty, scala-user
Thanks Oliver/Jon for your help.

Regards,
Jitendra

Oliver Ruebenacker

unread,
Feb 9, 2015, 7:59:09 AM2/9/15
to Jon Pretty, jitendra shelar, scala-user

     Hello,

  Upon further thought, my first solution won't work, because it takes treeNodeReads as an argument before it is initialized, i.e. while it is still null.

  The second solution id fine, because this ref is available immediately.

     Best, Oliver

Jitendra Shelar

unread,
Feb 9, 2015, 10:11:28 AM2/9/15
to Oliver Ruebenacker, Jon Pretty, scala-user
Ok Oliver.
Thanks for your help.

Regards,
Jitendra

You received this message because you are subscribed to a topic in the Google Groups "scala-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-user/k31IAyIHoMo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-user+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages