-
Notifications
You must be signed in to change notification settings - Fork 28
Examples of Type Class based JSON serialization
Here are some examples that will help in understanding how the type class based serialization occurs in sjson :-
Here's a sample session in the REPL that illustrates how you serialize and de-serialize:
scala> case class Name(name: String)
defined class Name
scala> import sjson.json._
import sjson.json._
scala> import DefaultProtocol._
import DefaultProtocol._
scala> implicit val NameFormat: Format[Name] = wrap[Name, String]("name")(_.name, Name)
NameFormat: sjson.json.Format[Name] = sjson.json.Generic$$anon$2@1eed0fb
scala> val n = Name("debasish ghosh")
n: Name = Name(debasish ghosh)
scala> import JsonSerialization._
import JsonSerialization._
scala> val js = tojson(n)
js: dispatch.json.JsValue = {"name" : "debasish ghosh"}
scala> dispatch.json.JsValue.toJson(js)
res0: String = {"name" : "debasish ghosh"}
scala> fromjson[Name](js)
res1: Name = Name(debasish ghosh)
scala> res1 == n
res2: Boolean = trueNote in the above example, wrap is the API that provides the type class implementation methods reads and writes. But all that's taken care of by the magic of implicits.
Here's the session in REPL:
scala> case class Shop(store: String, item: String, price: Int)
defined class Shop
scala> implicit val ShopFormat: Format[Shop] = asProduct3("store", "item", "price")(Shop)(Shop.unapply(_).get)
ShopFormat: sjson.json.Format[Shop] = sjson.json.Generic$$anon$4@42a751
scala> val shop = Shop("Shoppers Stop", "dress material", 1000)
shop: Shop = Shop(Shoppers Stop,dress material,1000)
scala> tojson(shop)
res3: dispatch.json.JsValue = {"store" : "Shoppers Stop", "item" : "dress material", "price" : 1000}
scala> dispatch.json.JsValue.toJson(res3)
res5: String = {"store" : "Shoppers Stop", "item" : "dress material", "price" : 1000}
scala> fromjson[Shop](res3)
res6: Shop = Shop(Shoppers Stop,dress material,1000)
scala> res6 == shop
res7: Boolean = trueIn Scala, a Product of 3 elements having types A, B and C is a class whose instances are all possible elements of the cartesian product of A, B and C. In the above example Shop is a Product3 and the method asProduct3 supplies the type class implementation methods for it.
Here's the sample REPL session:
scala> case class Address(street: String, city: String, zip: String)
defined class Address
scala> implicit val AddressFormat: Format[Address] =
| asProduct3("street", "city", "zip")(Address)(Address.unapply(_).get)
AddressFormat: sjson.json.Format[Address] = sjson.json.Generic$$anon$4@c00e55
scala> case class Contact(name: String, addresses: List[Address])
defined class Contact
scala> implicit val ContactFormat: Format[Contact] =
| asProduct2("name", "addresses")(Contact)(Contact.unapply(_).get)
ContactFormat: sjson.json.Format[Contact] = sjson.json.Generic$$anon$3@f61f70
scala> val contact = Contact("Debasish Ghosh",
| List(Address("monroe st", "denver", "80231"), Address("pine drive", "santa clara", "95054")))
contact: Contact = Contact(Debasish Ghosh,List(Address(monroe st,denver,80231), Address(pine drive,santa clara,95054)))
scala> tojson(contact)
res8: dispatch.json.JsValue = {"name" : "Debasish Ghosh", "addresses" : [{"street" : "monroe st", "city" : "denver", "zip" : "80231"}, {"street" : "pine drive", "city" : "santa clara", "zip" : "95054"}]}
scala> dispatch.json.JsValue.toJson(res8)
res9: String = {"name" : "Debasish Ghosh", "addresses" : [{"street" : "monroe st", "city" : "denver", "zip" : "80231"}, {"street" : "pine drive", "city" : "santa clara", "zip" : "95054"}]}
scala> fromjson[Contact](res8)
res10: Contact = Contact(Debasish Ghosh,List(Address(monroe st,denver,80231), Address(pine drive,santa clara,95054)))
scala> res10 == contact
res11: Boolean = trueAs can be seen from above, type class implementations for all built-in types like List etc. are automatically made available through implicits. For your own types, you need to define your Format implementation (as we did with Address above).
Here's a sample session at the REPL:
scala> import sjson.json._
import sjson.json._
scala> import DefaultProtocol._
import DefaultProtocol._
scala> val t1 = ("debasish", 12)
t1: (java.lang.String, Int) = (debasish,12)
scala> import JsonSerialization._
import JsonSerialization._
scala> tojson(t1)
res1: dispatch.json.JsValue = ["debasish", 12]
scala> dispatch.json.JsValue.toJson(res1)
res2: String = ["debasish", 12]
scala> fromjson[Tuple2[String, Int]](res1)
res3: (String, Int) = (debasish,12)
scala> res3 == t1
res4: Boolean = truescala> import scala.collection._
import scala.collection._
scala> val s = mutable.Set(12, 13, 10, 23, 25)
s: scala.collection.mutable.Set[Int] = Set(12, 25, 23, 13, 10)
scala> tojson(s)
res5: dispatch.json.JsValue = [13, 25, 12, 10, 23]
scala> dispatch.json.JsValue.toJson(res5)
res6: String = [13, 25, 12, 10, 23]
scala> fromjson[mutable.Set[Int]](res5)
res7: scala.collection.mutable.Set[Int] = Set(12, 25, 23, 13, 10)
scala> s == res7
res8: Boolean = truescala> import scala.collection._
import scala.collection._
scala> val t = immutable.Set(12, 13, 10, 23, 25)
t: scala.collection.immutable.Set[Int] = Set(12, 23, 13, 10, 25)
scala> tojson(t)
res9: dispatch.json.JsValue = [12, 23, 13, 25, 10]
scala> dispatch.json.JsValue.toJson(res9)
res10: String = [12, 23, 13, 25, 10]
scala> fromjson[immutable.Set[Int]](res9)
res11: scala.collection.immutable.Set[Int] = Set(12, 23, 13, 10, 25)
scala> t == res11
res12: Boolean = truescala> import sjson.json._
import sjson.json._
scala> import DefaultProtocol._
import DefaultProtocol._
scala> import JsonSerialization._
import JsonSerialization._
scala> val m = Map("100" -> "dg", "200" -> "mc")
m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map((100,dg), (200,mc))
scala> tojson(m)
res1: dispatch.json.JsValue = {"100" : "dg", "200" : "mc"}
scala> dispatch.json.JsValue.toJson(res1)
res2: String = {"100" : "dg", "200" : "mc"}
scala> fromjson[Map[String, String]](res1)
res3: Map[String,String] = Map((100,dg), (200,mc))
scala> res3 == m
res4: Boolean = trueYou can do that too. Here's a sample REPL session:
scala> import sjson.json._
import sjson.json._
scala> import JsonSerialization._
import JsonSerialization._
scala> import DefaultProtocol._
import DefaultProtocol._
scala> case class Address(street: String, city: String, zip: String)
defined class Address
scala> implicit val AddressFormat: Format[Address] =
| asProduct3("street", "city", "zip")(Address)(Address.unapply(_).get)
AddressFormat: sjson.json.Format[Address] = sjson.json.Generic$$anon$4@eae692
scala> case class Base(no: String, name: String, addresses: Array[Address])
defined class Base
scala> implicit val BaseFormat: Format[Base] =
| asProduct3("no", "name", "addresses")(Base)(Base.unapply(_).get)
BaseFormat: sjson.json.Format[Base] = sjson.json.Generic$$anon$4@13f957ascala> class Derived(no: String, name: String, addresses: Array[Address], special: Boolean) extends Base(no, name, addresses) {
| val specialFlag = special
| }
defined class Derived
scala> object DerivedProtocol extends DefaultProtocol {
| import dispatch.json._
| import JsonSerialization._
| implicit object DerivedFormat extends Format[Derived] {
| def reads(json: JsValue): Derived = {
| val b = fromjson[Base](json)
| json match {
| case JsObject(m) =>
| new Derived(b.no, b.name, b.addresses,
| fromjson[Boolean](m(JsString("specialFlag"))))
| case _ => throw new RuntimeException("JsObject expected")
| }
| }
| def writes(a: Derived): JsValue = {
| val o = tojson(a: Base)
| val JsObject(m) = o
| JsObject(m ++ List((tojson("specialFlag").asInstanceOf[JsString], tojson(a.specialFlag))))
| }
| }
| }
defined module DerivedProtocolscala> import DerivedProtocol._
import DerivedProtocol._
scala> val sa = new Derived("123", "debasish ghosh",
Array(Address("monroe st", "denver", "80231"), Address("tamarac st", "boulder", "80231")), true)
sa: Derived = Base(123,debasish ghosh,[LAddress;@ad7990)
scala> val acc = fromjson[Derived](tojson(sa))
acc: Derived = Base(123,debasish ghosh,[LAddress;@a528bc)