JSON basics introduced Reads and Writes converters which are used to convert between JsValue structures and other data types. This page covers in greater detail how to build these converters and how to use validation during conversion.

The examples on this page will use this JsValue structure and corresponding model:

JsPath is a core building block for creating Reads/Writes. JsPath represents the location of data in a JsValue structure. You can use the JsPath object (root path) to define a JsPath child instance by using syntax similar to traversing JsValue:

This will yield a type of FunctionalBuilder[Reads]#CanBuild2[Double, Double]. This is an intermediary object and you don’t need to worry too much about it, just know that it’s used to create a complex Reads.

Second call the apply method of CanBuildX with a function to translate individual values to your model, this will return your complex Reads. If you have a case class with a matching constructor signature, you can just use its apply method:

There is no validation on conversion to JsValue which makes the structure simpler and you won’t need any validation helpers.

The intermediary FunctionalBuilder#CanBuildX (created by and combinators) takes a function that translates a complex type T to a tuple matching the individual path Writes. Although this is symmetrical to the Reads case, the unapply method of a case class returns an Option of a tuple of properties and must be used with unlift to extract the tuple.

One special case that our example model doesn’t demonstrate is how to handle Reads and Writes for recursive types. JsPath provides lazyRead and lazyWrite methods that take call-by-name parameters to handle this: