Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to flatten a js array on Play using JSON transformers?

I have a Json of the following format:

  {
    "user": {
      "id": "1",
      "name": "Some User",
      "permGroups": [
        {
          "id": "group1",
          "name": "Group 1",
          "actions": [
            {
              "id": "action1",
              "name": "Action 1"
            }
          ]
        },
        {
          "id": "group2",
          "name": "Group 2",
          "actions": [
            {
              "id": "action2",
              "name": "Action 2"
            },
            {
              "id": "action3",
              "name": "Action 3"
            }
          ]
        }
      ]
    },
    "title": "New Role",
    "role_id": "56fea66c"
  }

How can I make a JSON Transformer in Play! 2.1, that will turn that into:

{
 "name": "New Role",
 "id" : "56fea66c",
 "permGroupIds": ["group1","group2"]
 "actions": ["action1", "action2", "action3"]
}

I have this working so far:

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

val jsonStr = """{"user":{"id":"1","name":"Some User","permGroups":[{"id":"group1","name":"Group 1","actions":[{"id":"action1","name":"Action 1"}]},{"id":"group2","name":"Group 2","actions":[{"id":"action3","name":"Action 3"},{"id":"action3","name":"Action 3"}]}]},"title":"New Role","role_id":"56fea66c"}"""
val jsonVal = Json.parse(jsonStr)

val jsonTransformer = (
    (__ \ 'name).json.copyFrom((__ \ 'title).json.pick) and
    (__ \ 'id).json.copyFrom((__ \ 'role_id).json.pick)
  ).reduce

jsonVal.transform(jsonTransformer)

this produces:

{
 "name": "New Role",
 "id" : "56fea66c",
}
like image 260
Johnny Everson Avatar asked Nov 11 '22 12:11

Johnny Everson


1 Answers

Here is one way to do it. This will ignore any perm groups or actions that don't have an id.

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

val jsonStr = """{"user":{"id":"1","name":"Some User","permGroups":[{"id":"group1","name":"Group 1","actions":[{"id":"action1","name":"Action 1"}]},{"id":"group2","name":"Group 2","actions":[{"id":"action3","name":"Action 3"},{"id":"action3","name":"Action 3"}]}]},"title":"New Role","role_id":"56fea66c"}"""

val jsonTransformer = (
  (__ \ 'name).json.copyFrom((__ \ 'user \ 'name).json.pick) and
  (__ \ 'id).json.copyFrom((__ \ 'role_id).json.pick) and
  (__ \ 'permGroupIds).json.copyFrom((__ \ 'user \ 'permGroups).read[List[JsObject]].map(permGroups =>
    JsArray(permGroups.flatMap(permGroup => (permGroup \ "id").toOption))
  )) and
  (__ \ 'actions).json.copyFrom((__ \ 'user \ 'permGroups).read[List[JsObject]].map(permGroups =>
    JsArray(permGroups.flatMap(permGroup => (permGroup \ "actions").asOpt[JsArray]).flatMap(_ \\ "id"))
  ))
).reduce

val transformed = Json.parse(jsonStr).transform(jsonTransformer)
Json.prettyPrint(transformed.get)

This produces

{
  "name" : "Some User",
  "id" : "56fea66c",
  "permGroupIds" : [ "group1", "group2" ],
  "actions" : [ "action1", "action3", "action3" ]
}
like image 59
jtesch Avatar answered Nov 13 '22 09:11

jtesch