A client library I'm using returns a java.util.Map[String, Object]
and I'd like to be able to serialize this into JSON and have my endpoint return a JSON HTTP response.
I've tried passing it directly to play.api.libs.json.Json.toJson
but I get this compiler error:
No Json serializer found for type java.util.Map[String,Object]. Try to implement an implicit Writes or Format for this type.
com.google.gson.Gson.toJson
seems to handle it just fine, but that method returns a String and I'd prefer my endpoint to return actual JSON and a plain text String.
Here's the best I've got so far:
def endpoint = Action {
val myMap: java.util.Map[String, Object] = service.getResponse
val gsonString: String = new Gson().toJson(myMap)
Ok(Json.parse(gsonString))
}
But this feels like a bit of a hack since I'm essentially serializing (with Gson), deserializing (with Play's Json), and then serializing again.
Should I just stick with what I have or is there a better way to do this?
1 Answer 1
There is no implicit Writes
available for Map[String,Object]
because there is no Writes
available for its value type, Object
. An value of type Object
could be of any subtype of Object
. It is equivalent to Scala's Any
. Its structure is unknown at compile time. Play's Json serialization relies solely on information known at compile time.
One solution would be to pattern match on the type and convert it to a more specific type, one which you have an instance of Writes
for.
Another would be to simply use the json string output from gson and render it using the as
method of the Ok
result to apply the appropriate content type: Ok(gsonString).as("application/json")
.