spray-json - List of case class property

2,557 views
Skip to first unread message

Gregg Carrier

unread,
Dec 31, 2011, 3:25:30 AM12/31/11
to spray...@googlegroups.com
I'm sure I'm missing something basic but I can't figure it out. I have
two case classes like this:

case class Foo(x: String, y: List[Bar])
case class Bar(z: Long)

then I have two formats like this:

object FooJsonProtocol extends DefaultJsonProtocol {
implicit val fooFormat = jsonFormat(Foo, "x", "y")
}

object BarJsonProtocol extends DefaultJsonProtocol {
implicit val barFormat = jsonFormat(Bar, "z")
}

I import them into scope like:

import FooJsonProtocol.fooFormat
import BarJsonProtocol.barFormat

But I get a compile error:

could not find implicit value for evidence parameter of type
FooJsonProtocol.JF[List[Bar]]

What am I missing? Thanks!

Gregg

elbowich

unread,
Dec 31, 2011, 7:25:38 AM12/31/11
to spray-user
Did you bring List format implicit into scope?

Saku

unread,
Dec 31, 2011, 7:47:03 AM12/31/11
to spray-user
Try using simply

import FooJsonProtocol._

it will import the List format from DefaultJsonProtocol as its what
your FooJsonProtocol extends

Mathias

unread,
Dec 31, 2011, 9:51:15 AM12/31/11
to spray...@googlegroups.com
Gregg,

as Saku already pointed out you need to bring the whole protocol into scope, not only the JsonFormat(s) for your class(es).
Also, you don't need to create separate protocol objects for each case class.
It's enough if you create one custom object and import all of its members:

object MyJsonProtocol extends DefaultJsonProtocol {


implicit val fooFormat = jsonFormat(Foo, "x", "y")

implicit val barFormat = jsonFormat(Bar, "z")
}

import MyJsonProtocol._

Cheers,
Mathias

---
mat...@spray.cc
http://www.spray.cc

Gregg Carrier

unread,
Dec 31, 2011, 11:14:28 AM12/31/11
to spray...@googlegroups.com
Thanks for the tips. I now have:

import MyJsonProtocol._

I am still getting the error I mentioned above, but I am also getting
an ambiguous implicit error - that's actually why I explicitly
imported my formatters in the first place.

ambiguous implicit values:
[error] both value StringMarshaller in trait DefaultMarshallers of
type => cc.spray.typeconversion.MarshallerBase[String]
[error] and method sprayJsonMarshaller in trait SprayJsonSupport of
type [A](implicit evidence$2:
cc.spray.json.JsonWriter[A])cc.spray.typeconversion.MarshallerBase[A]{lazy
val printer: cc.spray.json.JsonPrinter}
[error] match expected type cc.spray.http.ContentType =>
Option[cc.spray.http.ContentType] =>
cc.spray.typeconversion.Marshalling[String]
[error] ctx.fail(400, "user %s already
exists".format(u.get("_id")))

Is there a good way to deal with that one? Thanks for the help.

Mathias

unread,
Jan 1, 2012, 2:35:15 PM1/1/12
to spray...@googlegroups.com
Gregg,

ok, two more things you need to change:

1. To fix the "could not find implicit value" error you need to switch the declaration order in your MyJsonProtocol:

object MyJsonProtocol extends DefaultJsonProtocol {


implicit val barFormat = jsonFormat(Bar, "z")
implicit val fooFormat = jsonFormat(Foo, "x", "y")
}

2. To fix the "ambiguous implicit values" error you could switch to the latest snapshots of spray-server and spray-json or manually remove the ambiguity, e.g. by using an "import SprayJsonSupport._" (rather then mixing in the SprayJsonSupport trait) at a scope that doesn't include the `ctx.fail` line or by explicitly specifying the marshaller to be used:

ctx.fail(400, "user %s already exists".format(u.get("_id")))(StringMarshaller)


HTH and cheers,
Mathias

---
mat...@spray.cc
http://www.spray.cc

Kane Kim

unread,
Sep 27, 2013, 1:14:10 PM9/27/13
to spray...@googlegroups.com
Hello Mathias,

So, it's easy to unmarshal json object:
      case class Foo(name: List[Int])
      object MyJsonProtocol extends DefaultJsonProtocol {
        implicit val i = jsonFormat1(Foo)
      }
      import MyJsonProtocol._

What if i want to unmarshal a list? I've found it's even easier to do it explicitly: val args = request.asJson.convertTo[List[Int]], but what is the idiomatic way to do this?

Thanks!

Mathias Doenitz

unread,
Sep 30, 2013, 6:20:08 AM9/30/13
to spray...@googlegroups.com
Kane,

> What if i want to unmarshal a list? I've found it's even easier to do it
> explicitly: val args = request.asJson.convertTo[List[Int]], but what is the
> idiomatic way to do this?

if all you have on the JSON side really is only an array of numbers then your code should be good enough.

Cheers,
Mathias

---
mat...@spray.io
http://spray.io
> --
> You received this message because you are subscribed to the Google Groups "spray-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Sudeep Reddy Gaddam

unread,
Nov 20, 2015, 2:16:36 AM11/20/15
to spray.io User List
Hi Mathias,

What if I have Set[String] instead of List? How to handle marshalling/Unmarshalling??



case class User (
.....
friendsLists : Set[String])

object
UserJsonSupport extends DefaultJsonProtocol with SprayJsonSupport {

implicit val UserFormat = jsonFormat12(UserService.User)
}

Error:(39, 43) could not find implicit value for evidence parameter of type UserJsonSupport.JF[scala.collection.mutable.Set[String]]
implicit val UserFormat = jsonFormat12(UserService.User)
^

How to deal with such cases?

Age Mooij

unread,
Nov 21, 2015, 6:30:45 AM11/21/15
to spray...@googlegroups.com
FYI DefaultJsonProtocol only supports  immutable Sets, Seqs, Vectors, etc. It seems you are trying to marshal a mutable set and that is not supported. 


If you absolutely have to use mutable collections, you can most copy the immutable implementations and adjust them to fit your needs.

Hope this helps
Age


--
You received this message because you are subscribed to the Google Groups "spray.io User List" group.

To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages