Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active May 6, 2023 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dacr/0927400184aa6565c6dcc2cb212f4b14 to your computer and use it in GitHub Desktop.
Save dacr/0927400184aa6565c6dcc2cb212f4b14 to your computer and use it in GitHub Desktop.
ZIO learning - custom encoding/decoding / published by https://github.com/dacr/code-examples-manager #fccee49f-5fbe-4f91-bc78-366369f04294/c1983a4c71c397bf8203b3f8c991b8eb001d0b65
// summary : ZIO learning - custom encoding/decoding
// keywords : scala, zio, learning, json, pure-functional, @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 : fccee49f-5fbe-4f91-bc78-366369f04294
// created-on : 2022-01-22T08:12:30.292458847Z
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// ---------------------
//> using scala "3.2.2"
//> using dep "dev.zio::zio:2.0.13"
//> using dep "dev.zio::zio-test:2.0.13"
//> using dep "dev.zio::zio-json:0.5.0"
// ---------------------
import zio.*
import zio.json.*
import zio.json.ast.*
import zio.json.ast.Json.*
import zio.json.internal.{RetractReader, Write}
import zio.test.*
import zio.test.Assertion.*
import java.nio.file.Path
case class Something(
field1: Int,
field2: Boolean,
attributes: Map[String, Json]
)
object Something:
// implicit val encoder: JsonEncoder[Something] = DeriveJsonEncoder.gen
implicit val encoder: JsonEncoder[Something] = JsonEncoder[Json].contramap { something =>
val obj =
Obj("_field1" -> Num(something.field1), "_field2" -> Bool(something.field2))
.merge(Obj(something.attributes.toArray*))
obj
}
// implicit val decoder: JsonDecoder[Something] = DeriveJsonDecoder.gen
implicit val decoder: JsonDecoder[Something] = JsonDecoder[Obj].map { obj =>
val (fieldsTuples, attributesTuples) = obj.fields.partition { case (key, _) => key.startsWith("_") }
val fields = fieldsTuples.toMap
val field1 = fields.get("_field1").flatMap(_.as[Int].toOption).get // TODO to enhance of course
val field2 = fields.get("_field2").flatMap(_.as[Boolean].toOption).get // TODO to enhance of course
Something(field1 = field1, field2 = field2, attributes = attributesTuples.toMap)
}
object JsonTests extends ZIOSpecDefault:
def spec = suite("more complex json encoding/decoding")(
test("using data custom encoder/decoder approach") {
val json =
"""{
| "_field1" : 42,
| "_field2" : true,
| "attr1" : 424,
| "attr2" : "a value"
|}""".stripMargin
for {
obj <- ZIO.fromEither(json.fromJson)
something <- ZIO.fromEither(obj.as[Something])
} yield assertTrue(something.attributes.get("attr1") == Some(Num(424))) &&
assertTrue(something.toJsonPretty == json)
}
)
JsonTests.main(Array.empty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment