spray-json-derived-codecs


License

License

Categories

Categories

JSON Data
GroupId

GroupId

io.github.paoloboni
ArtifactId

ArtifactId

spray-json-derived-codecs_2.11
Last Version

Last Version

2.2.2
Release Date

Release Date

Type

Type

jar
Description

Description

spray-json-derived-codecs
spray-json-derived-codecs
Project URL

Project URL

https://github.com/paoloboni/spray-json-derived-codecs
Project Organization

Project Organization

io.github.paoloboni
Source Code Management

Source Code Management

https://github.com/paoloboni/spray-json-derived-codecs

Download spray-json-derived-codecs_2.11

How to add to project

<!-- https://jarcasting.com/artifacts/io.github.paoloboni/spray-json-derived-codecs_2.11/ -->
<dependency>
    <groupId>io.github.paoloboni</groupId>
    <artifactId>spray-json-derived-codecs_2.11</artifactId>
    <version>2.2.2</version>
</dependency>
// https://jarcasting.com/artifacts/io.github.paoloboni/spray-json-derived-codecs_2.11/
implementation 'io.github.paoloboni:spray-json-derived-codecs_2.11:2.2.2'
// https://jarcasting.com/artifacts/io.github.paoloboni/spray-json-derived-codecs_2.11/
implementation ("io.github.paoloboni:spray-json-derived-codecs_2.11:2.2.2")
'io.github.paoloboni:spray-json-derived-codecs_2.11:jar:2.2.2'
<dependency org="io.github.paoloboni" name="spray-json-derived-codecs_2.11" rev="2.2.2">
  <artifact name="spray-json-derived-codecs_2.11" type="jar" />
</dependency>
@Grapes(
@Grab(group='io.github.paoloboni', module='spray-json-derived-codecs_2.11', version='2.2.2')
)
libraryDependencies += "io.github.paoloboni" % "spray-json-derived-codecs_2.11" % "2.2.2"
[io.github.paoloboni/spray-json-derived-codecs_2.11 "2.2.2"]

Dependencies

compile (3)

Group / Artifact Type Version
org.scala-lang : scala-library jar 2.11.12
io.spray : spray-json_2.11 jar 1.3.6
com.chuusai : shapeless_2.11 jar 2.4.0-M1

test (3)

Group / Artifact Type Version
com.github.alexarchambault : scalacheck-shapeless_1.14_2.11 jar 1.2.3
org.scalatest : scalatest_2.11 jar 3.2.2
org.scalatestplus : scalacheck-1-14_2.11 jar 3.2.2.0

Project Modules

There are no modules declared in this project.

spray-json derived codecs

Build Status Latest version codecov.io License

JsonFormat derivation for algebraic data types, inspired by Play Json Derived Codecs and powered by shapeless.

The derivation currently supports:

  • sum types
  • product types
  • recursive types
  • polymorphic types

This library is built with Sbt 1.4.4 or later, and its master branch is built with Scala 2.13.4 by default but also cross-builds for 2.11.12 and 2.12.12.

Installation

If you use sbt add the following dependency to your build file:

libraryDependencies += "io.github.paoloboni" %% "spray-json-derived-codecs" % "2.2.2"

Usage

For automatic derivation, add the following import:

import spray.json.derived.auto._

If you prefer to explicitly define your formats, then you can use semi-auto derivation:

import spray.json.derived.semiauto._

Examples

Product types

Auto derivation
import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

case class Cat(name: String, livesLeft: Int)

object Test extends App {
  val oliver: Cat = Cat("Oliver", 7)
  val encoded     = oliver.toJson
  
  assert(encoded == """{"livesLeft":7,"name":"Oliver"}""".parseJson)
  assert(encoded.convertTo[Cat] == oliver)
}
Semi-auto derivation
import spray.json._
import spray.json.derived.semiauto._
import spray.json.DefaultJsonProtocol._

case class Cat(name: String, livesLeft: Int)

object Test extends App {
  implicit val format: JsonFormat[Cat] = deriveFormat[Cat]

  val oliver: Cat = Cat("Oliver", 7)
  val encoded     = oliver.toJson

  assert(encoded == """{"livesLeft":7,"name":"Oliver"}""".parseJson)
  assert(encoded.convertTo[Cat] == oliver)
}

Union types

Union types are encoded by using a discriminator field, which by default is type.

import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

sealed trait Pet
case class Cat(name: String, livesLeft: Int)   extends Pet
case class Dog(name: String, bonesHidden: Int) extends Pet

object Test extends App {
  val oliver: Pet   = Cat("Oliver", 7)
  val encodedOliver = oliver.toJson
  assert(encodedOliver == """{"livesLeft":7,"name":"Oliver","type":"Cat"}""".parseJson)
  assert(encodedOliver.convertTo[Pet] == oliver)

  val albert: Pet   = Dog("Albert", 3)
  val encodedAlbert = albert.toJson
  assert(encodedAlbert == """{"bonesHidden":3,"name":"Albert","type":"Dog"}""".parseJson)
  assert(encodedAlbert.convertTo[Pet] == albert)
}

The discriminator can be customised by annotating the union type with the @Discriminator annotation:

import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._
import spray.json.derived.Discriminator

@Discriminator("petType")
sealed trait Pet
case class Cat(name: String, livesLeft: Int)   extends Pet
case class Dog(name: String, bonesHidden: Int) extends Pet

object Test extends App {
  val oliver: Pet   = Cat("Oliver", 7)
  val encodedOliver = oliver.toJson
  assert(encodedOliver == """{"livesLeft":7,"name":"Oliver","petType":"Cat"}""".parseJson)
  assert(encodedOliver.convertTo[Pet] == oliver)
}

Recursive types

import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

sealed trait Tree
case class Leaf(s: String)            extends Tree
case class Node(lhs: Tree, rhs: Tree) extends Tree

object Test extends App {

  val obj: Tree = Node(Node(Leaf("1"), Leaf("2")), Leaf("3"))
  val encoded   = obj.toJson
  val expectedJson =
    """{
      |  "lhs": {
      |    "lhs": {
      |      "s": "1",
      |      "type": "Leaf"
      |    },
      |    "rhs": {
      |      "s": "2",
      |      "type": "Leaf"
      |    },
      |    "type": "Node"
      |  },
      |  "rhs": {
      |    "s": "3",
      |    "type": "Leaf"
      |  },
      |  "type": "Node"
      |}
      |""".stripMargin
  assert(encoded == expectedJson.parseJson)
  assert(encoded.convertTo[Tree] == obj)
}

Polymorphic types

import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

case class Container[T](value: T)

object Test extends App {

  val cString: Container[String] = Container("abc")
  val cStringEncoded             = cString.toJson
  assert(cStringEncoded == """{"value":"abc"}""".parseJson)
  assert(cStringEncoded.convertTo[Container[String]] == cString)

  val cInt: Container[Int] = Container(123)
  val cIntEncoded          = cInt.toJson
  assert(cIntEncoded == """{"value":123}""".parseJson)
  assert(cIntEncoded.convertTo[Container[Int]] == cInt)
}

Undefined optional members

By default, undefined optional members are not rendered:

import spray.json._
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

case class Dog(toy: Option[String])

object Test extends App {
  val aDog        = Dog(toy = None)
  val aDogEncoded = aDog.toJson
  assert(aDogEncoded.compactPrint == "{}")
}

It's possible to render undefined optional members as null values by specifying an alternative configuration. Just specify the alternative configuration as implicit value and enable the renderNullOptions flag:

import spray.json._
import spray.json.derived.Configuration
import spray.json.derived.auto._
import spray.json.DefaultJsonProtocol._

case class Dog(toy: Option[String])

object Test extends App {

  implicit val conf: Configuration = Configuration(renderNullOptions = true)

  val aDog        = Dog(toy = None)
  val aDogEncoded = aDog.toJson
  assert(aDogEncoded.compactPrint == """{"toy":null}""")
}

License

spray-json-derived-codecs is licensed under APL 2.0.

Versions

Version
2.2.2
2.2.1
2.2.0
2.1.0
2.0.4