spray-json
A lightweight, clean and simple JSON implementation in Scala
I have an optional field on my requests:
case class SearchRequest(url: String, nextAt: Option[Date])
My protocol is:
object SearchRequestJsonProtocol extends DefaultJsonProtocol {
implicit val searchRequestFormat = jsonFormat(SearchRequest, "url", "nextAt")
}
How do I mark the nextAt field optional, such that the following JSON objects will be correctly read and accepted:
{"url":"..."}
{"url":"...", "nextAt":null}
{"url":"...", "nextAt":"2012-05-30T15:23Z"}
I actually don't really care about the null case, but if you have details, it would be nice. I'm using spray-json, and was under the impression that using an Option would skip the field if it was absent on the original JSON object.
Source: (StackOverflow)
I understand that if I have:
case class Person(name: String)
I can use
object PersonJsonImplicits extends DefaultJsonProtocol {
implicit val impPerson = jsonFormat1(Person)
}
and thus serialize it with:
import com.example.PersonJsonImplicits._
import spray.json._
new Person("somename").toJson
however what If i have
trait Animal
case class Person(name: String) extends Animal
and I have somewhere in my code
val animal = ???
and I need to serialize it and I want to use json spray
which serializer should I add I was hoping to have something like:
object AnimalJsonImplicits extends DefaultJsonProtocol {
implicit val impAnimal = jsonFormat???(Animal)
}
where maybe I needed to add some matcher in order to check of what type is Animal so that if its a person I would direct it to person but found nothing... was reading https://github.com/spray/spray-json and don't understand how to do that..
so how can I serialize the set of
trait Animal
case class Person(name: String) extends Animal
with json spray?
Source: (StackOverflow)
I am trying to use spray-json in scala to recognize the choice between Ec2Provider and OpenstackProvider when converting to Json and back.
I would like to be able to give choices in "Provider", and if those choices don't fit the ones available then it should not validate.
My attempt at this can be seen in the following code:
import spray.json._
import DefaultJsonProtocol._
case class Credentials(username: String, password: String)
abstract class Provider
case class Ec2Provider(endpoint: String,credentials: Credentials) extends Provider
case class OpenstackProvider(credentials: Credentials) extends Provider
case class Infrastructure(name: String, provider: Provider, availableInstanceTypes: List[String])
case class InfrastructuresList(infrastructures: List[Infrastructure])
object Infrastructures extends App with DefaultJsonProtocol {
implicit val credFormat = jsonFormat2(Credentials)
implicit val ec2Provider = jsonFormat2(Ec2Provider)
implicit val novaProvider = jsonFormat1(OpenstackProvider)
implicit val infraFormat = jsonFormat3(Infrastructure)
implicit val infrasFormat = jsonFormat1(InfrastructuresList)
println(
InfrastructuresList(
List(
Infrastructure("test", Ec2Provider("nova", Credentials("user","pass")), List("1", "2"))
)
).toJson
)
}
Unfortunately, it fails because it can not find a formatter for Provider
abstract class.
test.scala:19: could not find implicit value for evidence parameter of type Infrastructures.JF[Provider]
Anyone have any solution for this?
Source: (StackOverflow)
I'm using spray-json to marshal lists of custom objects into JSON. I have the following case class and its JsonProtocol.
case class ElementResponse(name: String, symbol: String, code: String, pkwiu: String, remarks: String, priceNetto: BigDecimal, priceBrutto: BigDecimal, vat: Int, minInStock:Int, maxInStock: Int)
object JollyJsonProtocol extends DefaultJsonProtocol with SprayJsonSupport {
implicit val elementFormat = jsonFormat10(ElementResponse)
}
When I try to put in in a route like this one:
get {
complete {
List(new ElementResponse(...), new ElementResponse(...))
}
}
I get an error saying that:
could not find implicit value for evidence parameter of type spray.httpx.marshalling.Marshaller[List[pl.ftang.scala.polka.rest.ElementResponse]]
Perhaps you know what is the problem?
I'm using Scala 2.10.1 with spray 1.1-M7 and spray-json 1.2.5
Source: (StackOverflow)
I have the following route setup, but when my map is returned in the first complete block I get an error:
could not find implicit value for evidence parameter of type spray.httpx.marshalling.Marshaller[scala.collection.immutable.Map[String,String]]
import spray.routing.HttpService
import akka.actor.Actor
import spray.http.HttpRequest
import spray.routing.RequestContext
import spray.json.DefaultJsonProtocol._
class UserServiceActor extends Actor with RestUserService {
def actorRefFactory = context
def receive = runRoute(linkRoute)
}
trait RestUserService extends HttpService {
val userService = new LinkUserService
def linkRoute =
pathPrefix("user" / Segment) {
userId =>
path("link") {
parameters('service ! "YT") {
complete {
Map("status"-> "OK", "auth_url" -> "http://mydomain.com/auth")
}
}
}
}
}
According to this test I should be able to convert a Map to json when DefaultJsonProtocol._ is imported but even that's failing:
val map:Map[String, String] = Map("hi"->"bye")
map.toJson
Cannot find JsonWriter or JsonFormat type class for scala.collection.mutable.Map[String,String]
Not sure what's wrong :(
Source: (StackOverflow)
I'm finding myself in a situation in which I need to serialize into JSON a non case class.
Having a class as:
class MyClass(val name: String) {
def SaySomething() : String = {
return "Saying something... "
}
}
I've created a JsonProtocol for this class:
object MyClassJsonProtocol extends DefaultJsonProtocol {
implicit object MyClassJsonFormat extends JsonWriter[MyClass] {
override def write(obj: MyClass): JsValue =
JsObject(
"name" -> JsString(obj.name)
)
}
}
Later on in the code I import the protocol..
val aListOfMyClasses = List[MyClass]() ... // lets assume that has items and not an empty list
import spray.json._
import MyClassJsonProtocol._
val json = aListOfMyClasses.toJson
When trying to build the project I get the following error:
Cannot find JsonWriter or JsonFormat for type class List[MyClass]
spray-json has already a format for generic list and I'm providing a format for my class, what would be the problem?
Thanks in advance...!!!
Source: (StackOverflow)
I have the following code which uses spray-json to deserialise some JSON into a case class, via the parseJson
method.
Depending on where the implicit JsonFormat[MyCaseClass] is defined (in-line or imported from companion object), and whether there is an explicit type provided when it is defined, the code may not compile.
I don't understand why importing the implicit from the companion object requires it to have an explicit type when it is defined, but if I put it inline, this is not the case?
Interestingly, IntelliJ correctly locates the implicit parameters (via cmd-shift-p) in all cases.
I'm using Scala 2.11.7.
Broken Code - Wildcard import from companion object, inferred type:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
}
}
Results in:
Cannot find JsonReader or JsonFormat type class for SampleAppObject.MyCaseClass
Note that the same thing happens with an explicit import of the myCaseClassSchemaFormat
implicit.
Working Code #1 - Wildcard import from companion object, explicit type:
Adding an explicit type to the JsonFormat in the companion object causes the code to compile:
import SampleApp._
import spray.json._
class SampleApp {
import MyJsonProtocol._
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
object MyJsonProtocol extends DefaultJsonProtocol {
//Explicit type added here now
implicit val myCaseClassSchemaFormat: JsonFormat[MyCaseClass] = jsonFormat1(MyCaseClass)
}
}
Working Code #2 - Implicits inline, inferred type:
However, putting the implicit parameters in-line where they are used, without the explicit type, also works!
import SampleApp._
import spray.json._
class SampleApp {
import DefaultJsonProtocol._
//Now in-line custom JsonFormat rather than imported
implicit val myCaseClassSchemaFormat = jsonFormat1(MyCaseClass)
val inputJson = """{"children":["a", "b", "c"]}"""
println(s"Deserialise: ${inputJson.parseJson.convertTo[MyCaseClass]}")
}
object SampleApp {
case class MyCaseClass(children: List[String])
}
Source: (StackOverflow)
How to deserialize nested objects correctly in spray-json?
import spray.json._
case class Person(name: String)
case class Color(n: String, r: Int, g: Int, b: Int, p: Person)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object ColorJsonFormat extends RootJsonFormat[Color] {
def write(c: Color) = JsObject(
"color-name" -> JsString(c.n),
"Green" -> JsNumber(c.g),
"Red" -> JsNumber(c.r),
"Blue" -> JsNumber(c.b),
"person-field" -> JsObject("p-name" -> JsString(c.p.name))
)
def read(value: JsValue) = {
value.asJsObject.getFields("color-name", "Red", "Green", "Blue", "person-field") match {
case Seq(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue), JsObject(person)) =>
Color(name, red.toInt, green.toInt, blue.toInt, null) //gotta replace null with correct deserializer
case _ => throw new DeserializationException("Color expected")
}
}
}
}
import MyJsonProtocol._
val jsValue = Color("CadetBlue", 95, 158, 160, Person("guest")).toJson
jsValue.prettyPrint
val color = jsValue.convertTo[Color] //person is missing of course
On a side-note, how to spray-json help serializing to a map of fields (with nested map for nested objects)?
Source: (StackOverflow)
I have this route:
val routes =
pathPrefix("api") {
path("ElevationService" / DoubleNumber / DoubleNumber) { (long, lat) =>
post {
requestContext =>
println(long, lat)
}
}
}
This works nicely, I can call my ElevationService
as:
http://localhost:8080/api/ElevationService/39/80
The problem is, I also want to parse the body sent to me in the request as JSON. It looks as follows:
{
"first": "test",
"second": 0.50
}
I've managed to get it to work in a separate route following the documentation on the entity directive:
path("test") {
import scrive.actors.ScriveJsonProtocol
import spray.httpx.SprayJsonSupport._
post {
entity(as[ScriveRequest]) { scrive =>
complete(scrive)
}
}
}
But I don't know how to merge these two routes into one. Since they're wrapped in functions, I can't call the params long
, lat
from within the entity
function, they doesn't exist in that scope I suppose. The same goes or the other way around.
I want to be able to access both my params and my POST body, and then call a service passing all the data:
val elevationService = actorRefFactory.actorOf(Props(new ElevationService(requestContext)))
elevationService ! ElevationService.Process(long, lat, bodyParams)
Source: (StackOverflow)
I'm using spray and I need to return a json
object through a method.
val route =
path("all-modules") {
get {
respondWithMediaType(`text/html`) {
complete( configViewer.findAllModules.toString)
}
}
}
This prints ConfigResults(S1000,Success,List(testDataTypes, mandate, sdp))
But I need get this as the json
object. how can I do it?
I tried in this way
val route =
path("all-modules") {
get {
respondWithMediaType(`application/json`) {
complete{
configViewer.findAllModules
}
}
}
}
It gives an compilation error could not find implicit value for parameter marshaller: spray.httpx.marshalling.ToResponseMarshaller
Source: (StackOverflow)
I have a bunch of documents persisted in Apache Lucene with some names in russian, and when I'm trying to print them out it looks like this "\u0410\u0441\u043f\u0430\u0440"
, but not in cyrillic symbols. The project is in Scala. I've tried to fix this with Apache Commons unescapeJava
method, but it didn't help. Are there any other options?
Updated:
Project is writen with Spray framework and returns json like this.
{
"id" : 0,
"name" : "\u0410\u0441\u043f\u0430\u0440"
}
Source: (StackOverflow)
How do I serialize Map[String, Any] with spray-json? I try
val data = Map("name" -> "John", "age" -> 42)
import spray.json._
import DefaultJsonProtocol._
data.toJson
It says Cannot find JsonWriter or JsonFormat type class for scala.collection.immutable.Map[String,Any]
.
Source: (StackOverflow)
In some cases default values make more sense than optionals in case classes:
case class Car(numberOfWheels:Int = 4, color:String)
case class Car(numbeOfWheels:Option[Int], color:String) //silly
In the first case I'd expect to be able to easily convert the following json to an instance:
{"color":"red"}
But with a standard jsonFormat2(Car)
, spray-json complains about missing value for numberOfWheels
.
How do I work around this most cleanly?
Source: (StackOverflow)
I'm new to the Spray-Json API and I'm trying to parse a Json response from the Docker REST API.
There is a clean example of the usage of Spray-Json to parse this Google Map Json response :
{
"results" : [
{
"elevation" : 8815.7158203125,
"location" : {
"lat" : 27.988056,
"lng" : 86.92527800000001
},
"resolution" : 152.7032318115234
}
],
"status" : "OK"
}
In the above example the outermost level is an Object
. However, I need to directly parse a Json response whose outermost level is an Array
composed of containers information as shown below :
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
"Ports":[{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
"SizeRw":12288,
"SizeRootFs":0
},
{ ... },
{ ... }
]
Here is a code that I adapted from the Google map example :
package main
import ...
case class Container(id: String, image: String, command: String, created: Long, status: String, ports: List[Port], sizeRW: Long, sizeRootFs: Long)
case class Port(privatePort: Long, publicPort: Long, portType: String)
case class DockerApiResult[T](results: List[T])
object ContainerListJsonProtocol extends DefaultJsonProtocol {
implicit val portFormat = jsonFormat3(Port)
implicit val containerFormat = jsonFormat8(Container)
implicit def dockerApiResultFormat[T :JsonFormat] = jsonFormat1(DockerApiResult.apply[T])
}
object Main extends App {
implicit val system = ActorSystem("simple-spray-client")
import system.dispatcher // execution context for futures below
val log = Logging(system, getClass)
log.info("Requesting containers info...")
import ContainerListJsonProtocol._
import SprayJsonSupport._
val pipeline = sendReceive ~> unmarshal[DockerApiResult[Container]]
val responseFuture = pipeline {
Get("http://<ip-address>:4243/containers/json")
}
responseFuture onComplete {
case Success(DockerApiResult(Container(_,_,_,_,_,_,_,_) :: _)) =>
log.info("Id of the found image: {} ")
shutdown()
case Success(somethingUnexpected) =>
log.warning("The Docker API call was successful but returned something unexpected: '{}'.", somethingUnexpected)
shutdown()
case Failure(error) =>
log.error(error, "Couldn't get containers information")
shutdown()
}
def shutdown(): Unit = {
IO(Http).ask(Http.CloseAll)(1.second).await
system.shutdown()
}
}
And below is the exception I get (Object expected
) :
spray.httpx.PipelineException: MalformedContent(Object expected,Some(spray.json.DeserializationException: Object expected))
I certainly miss something obvious but How to parse a Json Array using Spray-Json?
Also, is there a simple way to do this without having to deal with custom JsonFormat or RootJsonFormat?
Source: (StackOverflow)
I'm trying to reprocude this or this, but I keep getting an error I am not able to fix...
First of all, here are my dependencies:
compile 'io.spray:spray-can_2.11:1.3.1'
compile 'io.spray:spray-routing_2.11:1.3.1',
compile 'io.spray:spray-json_2.11:1.2.6'
Now what I'm trying to do is:
class WHttpService extends Actor with HttpService with ActorLogging {
implicit def actorRefFactory = context
def receive = runRoute(route)
lazy val route = logRequest(showReq _) {
// Way too much imports but I tried all I could find
import spray.json._
import DefaultJsonProtocol._
import MasterJsonProtocol._
import spray.httpx.SprayJsonSupport._
path("server" / Segment / DoubleNumber / DoubleNumber) { (login, first, second) =>
get {
complete {
Answer(1, "test")
}
}
}
}
private def showReq(req : HttpRequest) = LogEntry(req.uri, InfoLevel)
}
With:
case object MasterJsonProtocol extends DefaultJsonProtocol with SprayJsonSupport {
import spray.json._
case class Answer(code: Int, content: String)
implicit val anwserFormat: JsonFormat[Answer] = jsonFormat2(Answer)
}
Now I get this error:
Error:(42, 19) type mismatch;
found : MasterJsonProtocol.Answer
required: spray.httpx.marshalling.ToResponseMarshallable
Answer(1, "test")
^
I tried a lot of things but can't manage to make it works.
I tried with
Answer(1, "test").toJson
Answer(1, "test").toJson.asJsObject
Finally what I did was
complete {
Answer(1, "test").toJson.compactPrint
}
This works but it is sent to the client as Content-Type: text/plain when I need application/json.
Anyone see what the problem is here?
Edit: I added a sample project on github https://github.com/ydemartino/spray-test
Source: (StackOverflow)