title | type | description | num | previous-page | next-page |
---|---|---|---|---|---|
How to serialize an object to JSON? | section | How to write JSON with Scala Toolkit. | 20 | json-deserialize | json-files |
{% include markdown.html path="_markdown/install-upickle.md" %}
uPickle can serialize your Scala objects to JSON, so that you can save them in files or send them over the network.
By default it can serialize primitive types such as Int
or String
, as well as standard collections such as Map
and List
.
{% tabs 'array' %} {% tab 'Scala 2 and 3' %}
valmap:Map[String, Int] =Map("Toolkitty"->3, "Scaniel"->5) valjsonString:String= upickle.default.write(map) println(jsonString) // prints: {"Toolkitty":3,"Scaniel":5}
{% endtab %} {% endtabs %}
In Scala, you can use a case class
to define your own data type. For example, to represent a pet owner with the name of its pets, you can
caseclassPetOwner(name: String, pets: List[String])
To be able to write a PetOwner
to JSON we need to provide a ReadWriter
instance for the case class PetOwner
. Luckily, upickle
is able to fully automate that:
{% tabs 'given' class=tabs-scala-version %} {% tab 'Scala 2' %}
importupickle.default._implicitvalownerRw:ReadWriter[PetOwner] = macroRW[PetOwner]
Some explanations:
- An
implicit val
is a value that can be automatically provided as an argument to a method or function call, without having to explicitly pass it. macroRW
is a method provided by uPickle that can generate a instances ofReadWriter
for case classes, using the information about its fields. {% endtab %} {% tab 'Scala 3' %}
importupickle.default.*caseclassPetOwner(name: String, pets: List[String]) derivesReadWriter
The derives
keyword is used to automatically generate given instances. Using the compiler's knowledge of the fields in PetOwner
, it generates a ReadWriter[PetOwner]
. {% endtab %} {% endtabs %}
This means that you can now write (and read) PetOwner
objects to JSON with upickle.default.write(petOwner)
.
Notice that you do not need to pass the instance of ReadWriter[PetOwner]
explicitly to the write
method. But it does, nevertheless, get it from the context, as "given" value. You may find more information about contextual abstractions in the Scala 3 Book.
Putting everything together you should get:
{% tabs 'full' class=tabs-scala-version %} {% tab 'Scala 2' %}
importupickle.default._caseclassPetOwner(name: String, pets: List[String]) implicitvalownerRw:ReadWriter[PetOwner] = macroRW valpetOwner=PetOwner("Peter", List("Toolkitty", "Scaniel")) valjson:String= write(petOwner) println(json) // prints: {"name":"Peter","pets":["Toolkitty","Scaniel"]}"
{% endtab %} {% tab 'Scala 3' %}
importupickle.default._caseclassPetOwner(name: String, pets: List[String]) derivesReadWritervalpetOwner=PetOwner("Peter", List("Toolkitty", "Scaniel")) valjson:String= write(petOwner) println(json) // prints: {"name":"Peter","pets":["Toolkitty","Scaniel"]}"
{% endtab %} {% endtabs %}