问题
I am attempting to produce JSON in a Scala app using json4s. Fairly straight forward, Here's some sample value I put together to test it in my Scalatra app:
import org.json4s._
import org.json4s.JsonDSL._
object JsonStub {
val getPeople =
("people" ->
("person_id" -> 5) ~
("test_count" -> 5))
}
In my controller, I simply have:
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.{DefaultFormats, Formats}
class FooController(mongoDb: MongoClient)(implicit val swagger: Swagger) extends ApiStack with NativeJsonSupport with SwaggerSupport {
get ("/people", operation(getPeople)) {
JsonStub.getPeople
}
}
The output I'm seeing in the browser however, is the following:
{
"_1": "people",
"_2": {
"person_id": 5,
"test_count": 5
}
}
Any clue where the _1
and _2
keys are coming from? I was expecting this output instead:
{
"people":{
"person_id": 5,
"test_count": 5
}
}
回答1:
What you're seeing in the output is a reflectively serialized tuple, which has fields _1
and _2
. This is because the return type that the compiler has inferred for JsonStub.getPeople
is Tuple2[String, JObject]
.
The json4s DSL uses implicit conversions to turn values like the tuple into a JValue
. But, if you don't tell the compiler you wanted a JValue
, it won't apply the conversion.
Ideally, this would result in a compile error, because you tried to produce JSON from something that isn't the right type. Unfortunately, because your web framework assumes you want to fall back to reflection-based serialization, it means there is another way to turn the tuple into JSON, which isn't what you wanted.
If you explicitly tell the compiler that you want a JValue
and not a Tuple2
, the DSL's implicit conversion will be applied in the correct place.
val getPeople: JValue =
("people" ->
("person_id" -> 5) ~
("test_count" -> 5))
来源:https://stackoverflow.com/questions/17534498/producing-json-in-a-scala-app-using-json4s