uPickle is a lightweight JSON and binary MessagePack serialization library for Scala. It is simple to use, flexible and easily customizable and has zero dependencies.

1 Introduction

1.1 Supported Types

Use write, read, writeBinary, readBinary. The indent parameter formats the output in indented format.

The data types include:

  • Boolean
  • Int, Short, Byte, Float, and Double. Large Long values too large for Javascript and are written as a string. Speical values include Infinity, -Infinity.
  • Char and String are serialzed as strings.
  • Immutable Array, Seq, Vector, List, SortedSet, Map etc. are serialized as JSON lists.
  • Options are serialized as JSON lists with 0 or 1 element.
  • Tuples from 1 to 22 are serialized as heterogenous JSON lists.
  • case class and case object, stand-alone.
  • sealed trait or sealed class hierarchy.
  • nulls seraialize into JSON nulls.
  • UUID
  • Duraion
  • Either

uPickle only throws exceptions on unpickling. Readability and writability is recursive: a class is only serializable if all its fields are serializable. Case classes are serialized using the apply and unapply methos on their companion objects.

If a field is missing upon deserialization, uPickle uses the ddefault value for the type if one exists.

1.2 Case Classes

Case classes of sizes 1-22 are serialized as JSON dictionaries. A serializer should be defined in the case class’s companion object as: implicit val rw: ReadWriter[MyCaseClass] = macroRW.

Sealed hierarchies are serialized as tagged values, the serialized object tagged with the full name of the instance’s class.

1.3 Read/Writing Other Things

Other than strings, uPickle can read/write form other sources such as CharSequence, Array[Byte], java.io.File and java.nio.file.path.

1.4 Common Operations

Use readwriter[T].bimap[V](toT, toV) function to create a pickler that reads/writes a type V, using the pickler for type T, by providing a conversion function between them.

More control can be done using readwriter[ujson.Value].bimap[V](toujson, toV) and raw JSON AST.

Use @upickle.implicits.key("name") to custom the key of a field. It can also be used to custom the tagged class name.

Use a custom pickler to change project-wide configuration.

1.5 Limitations

uPickle doesn’t support:

  • circular object graphs
  • reflective reading and writing
  • read/write of untyped values such as Any
  • read/write arbitrarily shaped objects
  • read/write case classes with multiple parameter lists

Due to a Scala bug, automatic sealed trait pickling can fail unpredictably. This can be fixed by using the macroRW and merge methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
sealed trait TypedFoo
object TypedFoo{
  import upickle.default._
  implicit val readWriter: ReadWriter[TypedFoo] = ReadWriter.merge(
    macroRW[Bar], macroRW[Baz], macroRW[Quz]
  )

  case class Bar(i: Int) extends TypedFoo
  case class Baz(s: String) extends TypedFoo
  case class Quz(b: Boolean) extends TypedFoo
}

2 uJson

uJson is uPickle’s JSON lib. It is used to manipulate JSON source and data structures without converting them into Scala case-classes.

2.1 uJson Values

You can use ujson to construct JSON blobs, either programmatically or parsing from strings, byte arrays or files.

ujson.Js AST (ujson.Value) is mutable. A ujson.Value can be one of the following types:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sealed trait Value

case class Str(value: String) extends Value
case class Obj(value: mutable.LinkedHashMap[String, Value]) extends Value
case class Arr(value: ArrayBuffer[Value]) extends Value
case class Num(value: Double) extends Value

sealed abstract class Bool extends Value
case object False extends Bool
case object True extends Bool

case object Null extends Value

You can use str, bool, num, arr, and obj etc to casts a ujson.Value to the specific sub-type and corresponding value. Each type has a Opt postfix method for optional values.

You can construct JSON data using the above types or primitive types:

1
2
3
4
5
6
7
8
9
val output = ujson.Arr(
  ujson.Obj("hello" -> ujson.Str("world"), "answer" -> ujson.Num(42)),
  ujson.Bool(true)
)

val output = ujson.Arr(
  ujson.Obj("hello" -> "world", "answer" -> 42),
  true
)

Use ujson.write to serialize a uJson value into string.

2.2 Converting To/From Scala Data Types

Scala case classes or other data structures can be converted to ujson.Js AST using upickle.default.writeJs and upickle.default.readJs or plian upickle.default.read, upickle.default.write.

uJson allows you convert between any of the following forms:

  • case class and Scala data types
  • ujson.Js AST
  • String, CharSequence, Array[Byte]
  • Third party JSON ASTs such as Argonaut, Circe, Json4s, and Play-Json

The case class can be sested. ujson.Value can be stroed as a case class field.