uPickle: a flexible Json Serializer

Table of contents
Reading Time: 2 minutes

uPickle serializer is a lightweight Json library for scala. uPickle is built on top of uJson which are used for easy manipulation of json without the need of converting it to a scala case class. We can even use uJson as standalone too. In this blog, I will focus only on uPickle library.

Note: uPickle does not support Scala 2.10; only 2.11 and 2.12 are supported

uPickle (pronounced micro-pickle) is a lightweight JSON serialization library which is fast than many other json serializers. I will talk more about the comparison of different serializers in my next blog. This blog will cover all the basic stuff about uPickle.

Features

  • Simple to use, with nice human-readable JSON output
  • Very high Performance; faster than Play-JsonCirce, or Argonaut by a large margin
  • Simple & easy to understand JSON Processing API, that should be instantly familiar to anyone whose processed JSON in Python, Ruby, or Javascript
  • Flexible and easily customizable
  • Zero dependencies; can be included in any project without worrying about conflicts
  • ScalaJS support, allowing transfer of structured data between the JVM and Javascript.

If you use uJson you will get basic operations to manipulate JSON:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


package object ujson{
def transform[T](t: Transformable, v: Visitor[_, T]) = t.transform(v)
def read(s: Transformable): Js.Value = transform(s, Js)
def copy(t: Js.Value): Js.Value = transform(t, Js)
def write(t: Js.Value, indent: Int = -1): String = {
transform(t, StringRenderer(indent)).toString
}
def writeTo(t: Js.Value, out: java.io.Writer, indent: Int = -1): Unit = {
transform(t, Renderer(out, indent))
}
def validate(s: Transformable): Unit = transform(s, NoOpVisitor)
def reformat(s: Transformable, indent: Int = -1): String = {
transform(s, StringRenderer(indent)).toString
}
def reformatTo(s: Transformable, out: java.io.Writer, indent: Int = -1): Unit = {
transform(s, Renderer(out, indent)).toString
}
// End ujson
}
view raw

gistfile1.txt

hosted with ❤ by GitHub

The uPickle library that uses uJson builds on top of these, exposing similar operations that work on any type T with a provided Reader or Writer:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


trait Api {
def read[T: Reader](s: Transformable): T = s.transform(reader[T])
def readJs[T: Reader](s: Js.Value): T = s.transform(reader[T])
def reader[T: Reader] = implicitly[Reader[T]]
def write[T: Writer](t: T, indent: Int = -1): String = {
transform(t).to(StringRenderer(indent)).toString
}
def writeJs[T: Writer](t: T): Js.Value = transform(t).to[Js.Value]
def writeTo[T: Writer](t: T, out: java.io.Writer, indent: Int = -1): Unit = {
transform(t).to(new Renderer(out, indent = indent))
}
def writer[T: Writer] = implicitly[Writer[T]]
def writable[T: Writer](t: T): Transformable = Transformable.fromTransformer(t, writer[T])
def readwriter[T: ReadWriter] = implicitly[ReadWriter[T]]
case class transform[T: Writer](t: T) extends Transformable{
def transform[V](f: ujson.Visitor[_, V]): V = writer[T].transform(t, f)
def to[V](f: ujson.Visitor[_, V]): V = transform(f)
def to[V](implicit f: Reader[V]): V = transform(f)
}
// End Api
}
view raw

gistfile1.txt

hosted with ❤ by GitHub

Now let’s see how it works.

First, we need to add the dependency in build.sbt

libraryDependencies += “com.lihaoyi” %% “upickle” % “0.6.5”

Then add this import in your code:

import upickle.default._

Scala primitive data types:

write(true: Boolean)              returns true (JSON Boolean)
write("Hello Upickle": String)    returns "Hello Upickle" (Json String)
write('A': Char)                  returns "A" (JSON String)
write(10: Int)                    returns 10 (JSON Number)
write(10: Float)                  returns 10 (JSON Number)
write(10.0: Double)               returns 10 (JSON Number)
write(1000000L: Long)             returns "10" (Json String)

Scala Collections:

write(List("Hello", "World"))     returns ["Hello","World"]    (JSON List)
write(Array("Hello", "uPickle"))  returns ["Hello","uPickle"]  (JSON List)

Scala Options:

write(Some("uPickle"))            returns ["uPickle"]   (JSON List)
write(None)                       returns []            (JSON List)

Scala case classes

case class MyuPickle(libraryName: String, _type: String) 
object MyuPickle { 
   implicit def rw: RW[MyuPickle] = macroRW 
} 
//now to serialize it 
write(MyuPickle("uPickle", "JSON Serializer"))                                   returns {"libraryName":"uPickle","_type":"JSON Serializer"}
//to deserialize it
read[MyuPickle]("{\"libraryName\":\"uPickle\",\"_type\":\"JSON Serializer\"}")   returns MyuPickle(uPickle,JSON Serializer)

Custom read/write

import upickle.default._

case class CustomPickle(libraryName: String, _type: String)
object CustomPickle {
  implicit val rw = upickle.default.readwriter[String].bimap[CustomPickle](
    customPickle => customPickle.libraryName + " " + customPickle._type,
    str => {
      val Array(name, _type) = str.split(" ", 2)
      new CustomPickle(name, _type)
    }
  )
}

write(CustomPickle("uPickle", "json serializer"))   returns "uPickle json serializer"
read[CustomPickle]("\"uPickle json serializer\"")   returns CustomPickle(uPickle,json serializer)

Supported Types

uPickle provides read/write for the following types:

  • BooleanByteCharShortIntLongFloatDouble
  • Tuples from 1 to 22
  • Immutable SeqListVectorSetSortedSetOptionArrayMaps, and all other collections with a reasonable CanBuildFrom implementation
  • DurationEither
  • Stand-alone case classes and case objects, and their generic equivalents,
  • Non-generic case classes and case objects that are part of a sealed trait or sealed classhierarchy
  • sealed trait and sealed classes themselves, assuming that all subclasses are picklable
  • UUIDs
  • null

In my next blog, I will compare different serializers and show you how uPickle stands out from all. But let me share the stats that I have got:

uPickle

Till then,

Happy reading…

Reference:

uPickle Documentation


knoldus-advt-sticker

Written by 

I am a Software Consultant at Knoldus Inc. I am a Scala Enthusiast. I am familiar with Object Oriented Programming Paradigms, and has also worked upon .NET based technologies. Aside from being a programmer, I am familiar with NoSQL database technologies such like Cassandra. I also worked on Lagom microservice architecture.

2 thoughts on “uPickle: a flexible Json Serializer3 min read

Comments are closed.