Skip to content

Instantly share code, notes, and snippets.

@netzwerg
Last active July 14, 2018 12:10
Show Gist options
  • Save netzwerg/521c066f52a0adb0e95b4af9538985d5 to your computer and use it in GitHub Desktop.
Save netzwerg/521c066f52a0adb0e95b4af9538985d5 to your computer and use it in GitHub Desktop.
Parsing heterogeneous JSON with Circe
package ch.netzwerg
import cats.data.Xor
import io.circe._
import io.circe.generic.auto._
import io.circe.parser._
import org.scalajs.dom.document
import scala.scalajs.js
object App extends js.JSApp {
case class Demo(variables: Seq[Variable])
case class Variable(name: String, `type`: String, value: VariableValue)
sealed trait VariableValue
case class StringVariableValue(value: String) extends VariableValue
case class LongVariableValue(value: Long) extends VariableValue
case class BooleanVariableValue(value: Boolean) extends VariableValue
object Variable {
implicit val decodeVariable: Decoder[Variable] = Decoder.instance(c => {
val `type` = c.downField("type").as[String]
val variableValueField = c.downField("value")
val variableValue = `type`.flatMap {
case "string" => variableValueField.as[String].map(StringVariableValue)
case "long" => variableValueField.as[Long].map(LongVariableValue)
case "boolean" => variableValueField.as[Boolean].map(BooleanVariableValue)
}
for {
name <- c.downField("name").as[String]
t <- `type`
vv <- variableValue
} yield Variable(name, t, vv)
}
)
}
@scala.scalajs.js.annotation.JSExport
override def main(): Unit = {
val json =
"""{
"variables": [
{
"name": "one",
"type": "string",
"value": "kermit"
},
{
"name": "two",
"type": "long",
"value": 42
},
{
"name": "three",
"type": "boolean",
"value": true
}
]
}"""
val errorOrResult = decode[Demo](json)
val out = document.getElementById("root")
errorOrResult match {
case Xor.Right(result) => out.innerHTML = "Result: " + result
case Xor.Left(error) => out.innerHTML = "Error: " + error
}
}
}
val root = Project(id = "demo", base = file("."))
.enablePlugins(ScalaJSPlugin)
.settings(
version := "0.1-SNAPSHOT",
scalaVersion := "2.11.8",
persistLauncher in Compile := true,
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % "0.9.1",
"io.circe" %%% "circe-scalajs" % "0.5.0-M2",
"io.circe" %%% "circe-parser" % "0.5.0-M2",
"io.circe" %%% "circe-generic" % "0.5.0-M2"
)
)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<div id="root">
<!-- Dynamic content -->
</div>
<!-- Include JavaScript dependencies -->
<script type="text/javascript" src="./target/scala-2.11/demo-jsdeps.js"></script>
<!-- Include Scala.js compiled code -->
<script type="text/javascript" src="./target/scala-2.11/demo-fastopt.js"></script>
<!-- Run JSApp -->
<script type="text/javascript" src="./target/scala-2.11/demo-launcher.js"></script>
</body>
</html>
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.10")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment