goo
goo

Reputation: 2280

Nesting json - Play 2.3

I'm trying to nest json like this:

case class Foo(id:Int, a:String, b:String)

def barJson =
  Json.obj("hello" -> "hi")

def getFooJson =
  Json.obj {
    "foos" -> Json.arr {
      fooTable.list.map { foo =>
        Json.toJson(foo) + barJson
      }
    }
  }

But I'm getting this error:

type mismatch;
[error]  found   : play.api.libs.json.JsObject
[error]  required: String

What am I doing wrong here & how can I fix it? The result I'm going after is something like this:

"foos":[
    {
      "a":"hi", 
      "b":"bye", 
      "bar": {
        "hello": "bye"
      }
    }, 
    {
      "a":"hi2", 
      "b":"bye2", 
      "bar": {
        "hello": "bye"
      }
    }
]

Upvotes: 2

Views: 288

Answers (1)

Travis Brown
Travis Brown

Reputation: 139058

The issue is that the + method for adding fields is on JsObject, and Json.toJson(foo) is only a JsValue. If you're sure your Writes for Foo always produces an object, you can use .as[JsObject]:

def getFooJson =
  Json.obj {
    "foos" -> Json.arr {
      fooTable.list.map { foo =>
        Json.toJson(foo).as[JsObject] + ("bar" -> barJson)
      }
    }
  }

Note also that you need to provide a key-value pair to + if you want the JSON in your expected result.

For what it's worth, I'd probably write something like the following:

val fooTableWrites = Writes.list(
  JsPath.write[Foo].transform(_.as[JsObject] + ("bar" -> barJson))
).transform(arr => Json.obj("foos" -> arr))

def getFooJson = fooTableWrites.writes(fooTable.list)

Does the same thing but you have more nicely composable pieces.

Upvotes: 1

Related Questions