Skip to content

Instantly share code, notes, and snippets.

@debasishg
Created April 8, 2011 10:25
Show Gist options
  • Save debasishg/909609 to your computer and use it in GitHub Desktop.
Save debasishg/909609 to your computer and use it in GitHub Desktop.
// problem with making it really optional in the general case ..
// what will be the output for the following ?
val str: Option[String] = None
tojson(str) // what ?
// hence ..
val str = None
fromjson[Option[String]](tojson[Option[String]](str)) should equal(str)
// really optional can be made using specific typeclass instance as follows
case class P(lastName: String, firstName: String, age: Option[Int] = None)
object PProtocol extends DefaultProtocol {
import dispatch.json._
import JsonSerialization._
implicit object PFormat extends Format[P] {
def reads(json: JsValue): P = json match {
case JsObject(m) =>
P(
fromjson[String](m(JsString("lastName"))),
fromjson[String](m(JsString("firstName"))),
m.get(JsString("age")).map(fromjson[Option[Int]](_)).getOrElse(None))
case _ => throw new RuntimeException("JsObject expected")
}
def writes(p: P): JsValue =
p.age.map(a =>
JsObject(List(
(tojson("lastName").asInstanceOf[JsString], tojson(p.lastName)),
(tojson("firstName").asInstanceOf[JsString], tojson(p.firstName)),
(tojson("age").asInstanceOf[JsString], tojson(a)))))
.getOrElse(
JsObject(List(
(tojson("lastName").asInstanceOf[JsString], tojson(p.lastName)),
(tojson("firstName").asInstanceOf[JsString], tojson(p.firstName)))))
}
}
// now None is really optional for class P serialization
import PProtocol._
val p = P("ghosh", "debasish")
println(tojson[P](p)) // prints {"lastName" : "ghosh", "firstName" : "debasish"}
println(fromjson[P](tojson[P](p))) // prints P(ghosh,debasish,None)
fromjson[P](tojson[P](p)) should equal(p)
@hseeberger
Copy link

Thank you.

Well, that works of course, but now I have to write the whole reads/writes-stuff instead of asProduct_.
Isn't there a chance to somehow build it into the asProduct_ methods, i.e. for case class fields?

By the way: If you stop calling your objects *Protocol and use companion objects instead (P in this case), you can get rid of the nasty imports.

@debasishg
Copy link
Author

regarding imports, doesn't case class create a companion object of its own ? Defining another one for the typeclass instance will (I think) give an error. Suggestions ?

regarding asProduct, I will investigate .. it will be a nice option though ..

@hseeberger
Copy link

Please look at my test case (trial-sjson): https://github.com/weiglewilczek/trial-json/blob/master/src/test/scala/SjsonSpec.scala
You won't find any errors there ;-)

To be more general: You can have companion objects for for case classes.

@debasishg
Copy link
Author

silly me :-( .. Not sure why I thought the companion object will be an error .. Thanks .. will change ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment