Simple JSON Objects

August 17, 2017

sbt configuration

/***
libraryDependencies += "io.argonaut" %% "argonaut" % "6.2.2"
*/

Common imports

import argonaut._
import argonaut.Argonaut._

A simple case class

case class Person(name: String, email: String, url: String)

val person: Person =
  Person( name = "James Earl Douglas"
        , email = "james@earldouglas.com"
        , url = "https://earldouglas.com"
        )

Encoding

implicit val encodePerson: EncodeJson[Person] =
  EncodeJson {
    (x: Person) =>
      ("name" := x.name) ->:
      ("email" := x.email) ->:
      ("url" := x.url) ->:
      jEmptyObject
  }

val encodedPerson: String = person.asJson.spaces2

println(s"\nencoded Person:\n$encodedPerson")

Decoding

implicit val decodePerson: DecodeJson[Person] =
  DecodeJson {
    (c: HCursor) =>
      for {
        name  <- (c --\ "name").as[String]
        email <- (c --\ "email").as[String] flatMap { email =>
                   DecodeResult {
                     if (email.matches("[^@]+@[^@]+")) Right(email)
                     else Left((s"invalid email $email", c.history))
                   }
                 }
        url   <- (c --\ "url").as[String]
      } yield Person( name = name
                    , email = email
                    , url = url
                    )
  }

val decodedPerson: Either[String, Person] =
  """|{
     |  "name": "James Earl Douglas",
     |  "email": "james@earldouglas.com",
     |  "url": "https://earldouglas.com"
     |}""".stripMargin.decodeEither[Person]

println(s"\ndecoded Person:\n$decodedPerson")

Demo

This file is literate Scala, and can be run using Codedown:

$ curl -s https://earldouglas.com/posts/reference/argonaut/simple.md |
  codedown scala > script.scala
$ sbt -Dsbt.main.class=sbt.ScriptMain script.scala

encoded Person:
{
  "url" : "https://earldouglas.com",
  "email" : "james@earldouglas.com",
  "name" : "James Earl Douglas"
}

decoded Person:
Right(Person(James Earl Douglas,james@earldouglas.com,https://earldouglas.com))