Last active
May 25, 2024 10:20
-
-
Save dacr/79d03a9883fb2dc9c4d85e6f3711a002 to your computer and use it in GitHub Desktop.
Circe scala json API cookbook as unit test cases. / published by https://github.com/dacr/code-examples-manager #b22ead77-d362-409d-baf7-8070a5def33f/86b499a1820c1bbf328c46f5da163f9d7ee73cb3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// summary : Circe scala json API cookbook as unit test cases. | |
// keywords : scala, scalatest, circe, json, @testable | |
// publish : gist | |
// authors : David Crosson | |
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2) | |
// id : b22ead77-d362-409d-baf7-8070a5def33f | |
// created-on : 2019-05-25T20:49:38Z | |
// managed-by : https://github.com/dacr/code-examples-manager | |
// run-with : scala-cli $file | |
// --------------------- | |
//> using scala "3.4.2" | |
//> using dep "org.scalatest::scalatest:3.2.16" | |
//> using dep "io.circe::circe-parser:0.14.1" | |
//> using dep "io.circe::circe-generic:0.14.1" | |
//> using objectWrapper | |
// --------------------- | |
import io.circe.* | |
import io.circe.generic.auto.* | |
import io.circe.parser.* | |
import io.circe.syntax.* | |
import io.circe.Encoder.* | |
import org.scalatest.* | |
import matchers.* | |
import OptionValues.* | |
import java.time.OffsetDateTime | |
import java.util.UUID | |
// ============================================================================= | |
case class Someone(name: String, age: Int) | |
case class Event(when: OffsetDateTime, who: Someone, what: String) | |
case class SomethingOptional(id: String, content: Option[String], items: Option[Array[String]]) | |
case class Record(id: String, items: List[String]) | |
case class RecordWithUUID(uuid: UUID) | |
// ============================================================================= | |
class JsonCirceCookBook extends flatspec.AnyFlatSpec with should.Matchers { | |
override def suiteName = "JsonCirceCookBook" | |
"circe" should "parse json strings" in { | |
val json = """{"name":"John Doe", "age":42}""" | |
val doc = parse(json).getOrElse(Json.Null) | |
val cursor = doc.hcursor | |
cursor.get[String]("name").toOption.value should equal("John Doe") | |
} | |
it should "parse complex data types perfectly" in { | |
val json = """{"who":{"name":"John Doe", "age":42}, "what":"new", "when":"2020-10-24T08:56:36.294Z"}""" | |
val event = parse(json).flatMap(_.as[Event]).toOption | |
event.value.who.name shouldBe "John Doe" | |
event.value.who.age shouldBe 42 | |
event.value.what shouldBe "new" | |
event.value.when shouldBe OffsetDateTime.parse("2020-10-24T08:56:36.294Z") | |
} | |
it should "support optional field" in { | |
val json1 = """{"id":"42"}""" | |
val json2 = """{"id":"42", "content":"yes", "items":["a","b"]}""" | |
parse(json1).flatMap(_.as[SomethingOptional]).toOption.value.content shouldBe None | |
parse(json1).flatMap(_.as[SomethingOptional]).toOption.value.items shouldBe None | |
parse(json2).flatMap(_.as[SomethingOptional]).toOption.value.content shouldBe Some("yes") | |
parse(json2).flatMap(_.as[SomethingOptional]).toOption.value.items.value.size shouldBe 2 | |
} | |
it should "support arrays" in { | |
val json = """{"id":"42", "items":["yes", "no"]}""" | |
parse(json).flatMap(_.as[Record]).toOption.value.id shouldBe "42" | |
} | |
it should "support uuid" in { | |
val json = """{"uuid":"c5e4e9c6-99d0-4bad-ba14-c9b1c20f5530"}""" | |
parse(json).flatMap(_.as[RecordWithUUID]).toOption.value.uuid shouldBe UUID.fromString("c5e4e9c6-99d0-4bad-ba14-c9b1c20f5530") | |
} | |
it should "be able to handle supplementary fields" in { | |
val json = """{"name":"joe", "age":42, "gender":"male"}""" | |
parse(json).flatMap(_.as[Someone]).toOption.value.name shouldBe "joe" | |
} | |
it should "AST" in { | |
val json = """{"name":"joe"}""" | |
val result = parse(json).flatMap(_.as[Json]).toOption.value | |
val job = result.asObject | |
job.flatMap(_.apply("name")).flatMap(_.asString).value shouldBe "joe" | |
} | |
it should "be possible to create a JsonObject by hand using generic JsonObject" in { | |
val job1:Json = JsonObject().add("name", encodeString("joe")).asJson | |
val job2:Json = | |
JsonObject() | |
.add("name", encodeString("joe")) | |
.add("address", | |
JsonObject() | |
.add("country", encodeString("france")) | |
.asJson | |
).asJson | |
val job3:Json = | |
JsonObject("name"->encodeString("joe")).asJson | |
val job4:Json = Json.fromJsonObject(JsonObject("name"->encodeString("joe"))) | |
} | |
it should "be possible to create a JsonObject by hand using Map data structure" in { | |
//val scason = Map("name"->"joe", "address"->Map("country"->"spain")) | |
//val job1:Json = scason.asJson | |
//val job2 = io.circe. | |
info("This is not possible by choice & design !") | |
} | |
} | |
org.scalatest.tools.Runner.main(Array("-oDF", "-s", classOf[JsonCirceCookBook].getName)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment