Stringly Typed

August 17, 2017

This is probably not a good idea.

sbt configuration

/***
libraryDependencies += "io.argonaut" %% "argonaut-scalaz" % "6.2"
*/

Common imports

import argonaut._
import argonaut.Argonaut._
import scalaz._
import scalaz.Scalaz._
import java.net.URL

A URL to be stringified

val url: URL = new URL("https://earldouglas.com")

Encoding

implicit val showURL: Show[URL] =
  new Show[URL] {
    override def shows(x: URL): String = x.toString
  }
implicit def encodeShow[A:Show]: EncodeJson[A] =
  EncodeJson { x: A => jString(x.shows) }

val encodedURL: String = url.asJson.spaces2

println(s"\nencoded URL:\n$encodedURL")

Decoding

trait Read[A] {
  def read(x: String): A
}

implicit class ReadOps(val x: String) {
  def read[A:Read]: A = implicitly[Read[A]].read(x)
}

implicit val readURL: Read[URL] =
  new Read[URL] {
    override def read(x: String): URL = new URL(x)
  }
implicit def decodeShow[A:Read]: DecodeJson[A] =
  DecodeJson { _.as[String] map { _.read[A] } }

val decodedURL: Either[String, URL] =
  "\"https://earldouglas.com\"".decodeEither[URL]

println(s"\ndecoded URL:\n$decodedURL")

Demo

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

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

encoded URL:
"https://earldouglas.com"

decoded URL:
Right(https://earldouglas.com)