Skip to content

Commit 9948f5b

Browse files
Merge pull request #1375 from mdipirro/scala-400
SCALA-400 Add code for zio-json article
2 parents 0984c30 + 603e5ec commit 9948f5b

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,10 @@ lazy val zio2 = (project in file("zio-2"))
648648
name := "zio-2",
649649
scalaVersion := scala3Version,
650650
libraryDependencies += "dev.zio" %% "zio" % zioVersion,
651+
libraryDependencies += "dev.zio" %% "zio-json" % "0.6.2",
651652
libraryDependencies += "dev.zio" %% "zio-test" % zioVersion % Test,
652653
libraryDependencies += "dev.zio" %% "zio-test-sbt" % zioVersion % Test,
654+
libraryDependencies ++= scalaTestDeps,
653655
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
654656
)
655657

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.baeldung.scala.zio.json
2+
3+
import zio.json.*
4+
5+
sealed trait Command
6+
case class Start(timeout: Long) extends Command
7+
case object Stop extends Command
8+
case class Kill(reason: String, force: Boolean) extends Command
9+
10+
@jsonDiscriminator("type")
11+
sealed trait Command2
12+
case class Start2(timeout: Long) extends Command2
13+
case object Stop2 extends Command2
14+
case class Kill2(reason: String, force: Boolean) extends Command2
15+
16+
object Start {
17+
implicit val encoder: JsonEncoder[Start] = DeriveJsonEncoder.gen[Start]
18+
implicit val decoder: JsonDecoder[Start] = DeriveJsonDecoder.gen[Start]
19+
}
20+
21+
object Command {
22+
implicit val encoder: JsonEncoder[Command] = DeriveJsonEncoder.gen[Command]
23+
implicit val decoder: JsonDecoder[Command] = DeriveJsonDecoder.gen[Command]
24+
}
25+
26+
object Command2 {
27+
implicit val encoder: JsonEncoder[Command2] = DeriveJsonEncoder.gen[Command2]
28+
implicit val decoder: JsonDecoder[Command2] = DeriveJsonDecoder.gen[Command2]
29+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.baeldung.scala.zio.json
2+
3+
import org.scalatest.matchers.should.Matchers
4+
import org.scalatest.wordspec.AnyWordSpec
5+
import zio.json.*
6+
7+
class DecodingUnitTest extends AnyWordSpec with Matchers {
8+
"zio-json" should {
9+
"decode a JSON object to a case class" in {
10+
"""{"timeout":789}""".fromJson[Start] shouldBe Right(Start(789))
11+
}
12+
13+
"return a decoding error if the JSON is not correct" in {
14+
"""{"duration":789}""".fromJson[Start] shouldBe Left(".timeout(missing)")
15+
}
16+
17+
"decode a JSON object with extra fields to a case class" in {
18+
"""{"timeout":789, "extra": "field"}""".fromJson[Start] shouldBe Right(
19+
Start(789)
20+
)
21+
}
22+
23+
"decode an ADT to JSON" in {
24+
"""{"Start":{"timeout":100}}""".fromJson[Command] shouldBe Right(
25+
Start(100)
26+
)
27+
"""{"Stop":{}}""".fromJson[Command] shouldBe Right(Stop)
28+
"""{"Kill":{"reason":"Random reason","force":false}}"""
29+
.fromJson[Command] shouldBe Right(
30+
Kill("Random reason", false)
31+
)
32+
}
33+
34+
"decode Stop to JSON" in {
35+
implicit val decoder: JsonDecoder[Stop.type] =
36+
implicitly[JsonDecoder[String]].map(_ => Stop)
37+
38+
"""{"Start":{"timeout":100}}""".fromJson[Command] shouldBe Right(
39+
Start(100)
40+
)
41+
""""Stop"""".fromJson[Stop.type] shouldBe Right(Stop)
42+
"""{"Kill":{"reason":"Random reason","force":false}}"""
43+
.fromJson[Command] shouldBe Right(
44+
Kill("Random reason", false)
45+
)
46+
}
47+
48+
"use a discriminator" in {
49+
"""{"type":"Start2","timeout":100}""".fromJson[Command2] shouldBe Right(
50+
Start2(100)
51+
)
52+
"""{"type":"Stop2"}""".fromJson[Command2] shouldBe Right(Stop2)
53+
"""{"type":"Kill2","reason":"Random reason","force":false}"""
54+
.fromJson[Command2] shouldBe Right(
55+
Kill2("Random reason", false)
56+
)
57+
}
58+
59+
"fail if there's no discriminator" in {
60+
"""{"timeout":100}""".fromJson[Command2] shouldBe Left(
61+
"(missing hint 'type')"
62+
)
63+
}
64+
}
65+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.baeldung.scala.zio.json
2+
3+
import org.scalatest.matchers.should.Matchers
4+
import org.scalatest.wordspec.AnyWordSpec
5+
import zio.json.*
6+
7+
class EncodingUnitTest extends AnyWordSpec with Matchers {
8+
"zio-json" should {
9+
"encode a case class to JSON" in {
10+
Start(100).toJson shouldBe """{"timeout":100}"""
11+
}
12+
13+
"encode an ADT to JSON" in {
14+
(Start(100): Command).toJson shouldBe """{"Start":{"timeout":100}}"""
15+
(Stop: Command).toJson shouldBe """{"Stop":{}}"""
16+
(Kill(
17+
reason = "Random reason",
18+
force = false
19+
): Command).toJson shouldBe """{"Kill":{"reason":"Random reason","force":false}}"""
20+
}
21+
22+
"encode Stop to JSON" in {
23+
implicit val encoder: JsonEncoder[Stop.type] =
24+
implicitly[JsonEncoder[String]].contramap(_.toString())
25+
26+
(Start(100): Command).toJson shouldBe """{"Start":{"timeout":100}}"""
27+
Stop.toJson shouldBe """"Stop""""
28+
(Kill(
29+
reason = "Random reason",
30+
force = false
31+
): Command).toJson shouldBe """{"Kill":{"reason":"Random reason","force":false}}"""
32+
}
33+
34+
"use a discriminator" in {
35+
(Start2(
36+
100
37+
): Command2).toJson shouldBe """{"type":"Start2","timeout":100}"""
38+
(Stop2: Command2).toJson shouldBe """{"type":"Stop2"}"""
39+
(Kill2(
40+
reason = "Random reason",
41+
force = false
42+
): Command2).toJson shouldBe """{"type":"Kill2","reason":"Random reason","force":false}"""
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)