Reputation: 456
I came across this problem at work recently, and couldn't figure out how to accomplish it with Scala. I'm using the play framework, so I have access to the JSON library. I'm new to Scala, and would like to know how to accomplish this specific task. The sample data is an example of what the real data looks like.
In the end, I wasn't able to figure this out and instead parsed the data in a PHP consumer of this Scala API. I'd love to change that :)
Thanks!
Given the following tupple:
(("GET","a/b/c"),("POST","a/c/d"),("POST","f/e/x/r"),("GET","a/c/f/f"))
Produce the following JSON:
{
"a": {
"b": {
"c": {
"GET" : "GET"
}
},
"c": {
"d": {
"POST": "POST"
},
"f": {
"f": {
"GET": "GET"
}
}
}
},
"f": {
"e": {
"x": {
"r": {
"POST": "POST"
}
}
}
}
}
Upvotes: 1
Views: 332
Reputation: 5315
First off, you probably don't want your data to be in a tuple. Tuples are for holding different type of values in a statically fixed number. You'll be better off with List[(String, String)]
which allows you to add as many routes as you want (while your example is stuck with 4)
Next, you need to recursively nest objects, if you have the different segments in your path. This can be done quite easily with foldRight
:
def nestedObjects(inside: JsObject, nesters: Seq[String]): JsObject =
nesters.foldRight(inside)((nester, in) => Json.obj(nester -> in)
Now, we need to extract that list of nesters from the path you are given, and define the inside object:
def treatPair(method: String, path: String): JsObject = {
val nesters = path.split("/")
val inside = Json.obj(method -> method)
nestedObjects(inside, nesters)
}
Now, we're left to merging all results, for which play-json already have a method: deepMerge
def reduceList(routes: List[(String, String)]): JsObject = {
routes.map {
case (method, path) => treatPair(method, path) //apply treatPair on each pair
}.fold(Json.obj())(_ deepMerge _) //merge them two-by-two
Upvotes: 4