0

An example of the sort of objects I need to grab from my json can be found in the following example(src):

{
  "test": {
    "attra": "2017-10-12T11:17:52.971Z",
    "attrb": "2017-10-12T11:20:58.374Z"
  },
  "dummyCheck": false,
  "type": "object",
  "ruleOne": {
    "default": 2557
  },
  "ruleTwo": {
    "default": 2557
  }
}

From the example above I want to access the default value under "ruleOne". I've tried messing about with several different things below but I seem to be struggling. I can grab values like "dummyCheck" ok. What's the best way to key into where I need to go? Example of how I am trying to get the value below:

import org.json4s._
import org.json4s.native.JsonMethods._
import org.json4s.DefaultFormats

implicit val formats = DefaultFormats
val test = parse(src)
println((test \ "ruleOne.default").extract[Integer])

Edit: To further extend what is above:

  def extractData(data: java.io.File) = {
    val json = parse(data)
    val result = (json \ "ruleOne" \ "default").extract[Int]
    result
  }

If I was to extend the above into a function that is called by passing in:

extractData(src)

That would only ever give me RuleOne.default.. is there a way I could extend it so that I could dynamically pass it multiple string arguments to parse (like a splat)

  def extractData(data: java.io.File, path: String*) = {
    val json = parse(data)
    val result = (json \ path: _*).extract[Int]
    result
  }

so consuming it would be like

extractData(src, "ruleOne", "default")
1
  • 2
    (test \ "ruleOne" \ "default").extract[Int] Commented Apr 4, 2018 at 20:42

1 Answer 1

2

This here works with "json4s-jackson" % "3.6.0-M2", but it should work in exactly the same way with native backend.

val src = """
  |{
  |  "test": {
  |    "attra": "2017-10-12T11:17:52.971Z",
  |    "attrb": "2017-10-12T11:20:58.374Z"
  |  },
  |  "dummyCheck": false,
  |  "type": "object",
  |  "ruleOne": {
  |    "default": 2557
  |  },
  |  "ruleTwo": {
  |    "default": 2557
  |  }
  |}""".stripMargin

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.DefaultFormats

implicit val formats = DefaultFormats
val test = parse(src)
println((test \ "ruleOne" \ "default").extract[Int])

Output:

2557

To make it work with native, simply replace

import org.json4s.jackson.JsonMethods._

by

import org.json4s.native.JsonMethods._

and make sure that you have the right dependencies.


EDIT

Here is a vararg method that transforms string parameters into a path:

def extract(json: JValue, path: String*): Int = {
  path.foldLeft(json)(_ \ _).extract[Int]
}

With this, you can now do:

println(extract(test, "ruleOne", "default"))
println(extract(test, "ruleTwo", "default"))

Note that it accepts a JValue, not a File, because the version with File would be unnecessarily painful to test, whereas JValue-version can be tested with parsed string constants.

Sign up to request clarification or add additional context in comments.

3 Comments

is there anyone I could use a splat operator to dynamically chain my root to the data?
I have expanded on the original question with an edit that hopefully explains it better
@Curious_Bop Take a look at this foldLeft solution for a very similar question for XML. I'll try to update my answer to do the same in JSON.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.