Domanda

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
  }
}
È stato utile?

Soluzione

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))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top