Skip to content

Instantly share code, notes, and snippets.

@fanf
Last active April 20, 2022 08:45
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 fanf/8e77ffcb6af1be02670338254356135d to your computer and use it in GitHub Desktop.
Save fanf/8e77ffcb6af1be02670338254356135d to your computer and use it in GitHub Desktop.
/*
* These codec used to work with zio-json 2.0.0-M3 but are not working anymore with
* zio-json 3.0.0-R7.
* Even more strange, if I remove the encoder part (ie from codec to simple decoder),
* then the decoding works in 3.0.0-R7.
* It looks like a bug
*/
package test
import org.junit.runner.RunWith
import org.specs2.mutable.Specification
import org.specs2.runner.JUnitRunner
import zio.json._
import zio.json.internal.Write
@RunWith(classOf[JUnitRunner])
class ReproduceErrorTest extends Specification {
final case class JsonExpectedValueId7_1(id: String, v: String)
final case class JsonValueExpectedReport7_1(
vid: String
, vs: List[Either[List[String],JsonExpectedValueId7_1]]
)
implicit lazy val codecJsonExpectedValueId7_1: JsonCodec[JsonExpectedValueId7_1] = DeriveJsonCodec.gen
implicit lazy val codecJsonEitherValue: JsonCodec[Either[List[String],JsonExpectedValueId7_1]] = {
// invariance is complicated
def toRight(x: JsonExpectedValueId7_1): Either[List[String],JsonExpectedValueId7_1] = Right(x)
def toLeft(x: List[String]): Either[List[String],JsonExpectedValueId7_1] = Left(x)
val decoder = JsonDecoder[List[String]].map(toLeft).orElse(codecJsonExpectedValueId7_1.decoder.map(toRight))
val encoder = new JsonEncoder[Either[List[String],JsonExpectedValueId7_1]] {
override def unsafeEncode(a: Either[List[String], JsonExpectedValueId7_1], indent: Option[Int], out: Write): Unit = {
a match {
case Left(x) => JsonEncoder[List[String]].unsafeEncode(x, indent, out)
case Right(x) => codecJsonExpectedValueId7_1.encoder.unsafeEncode(x, indent, out)
}
}
}
JsonCodec(encoder, decoder)
}
implicit lazy val codecJsonValueExpectedReport7_1: JsonCodec[JsonValueExpectedReport7_1] = DeriveJsonCodec.gen
sequential
"the left case" >> {
import zio.json._
val jsonMin =
"""
{
"vid": "Command execution",
"vs": [
[ "/bin/echo \"restore\"" ]
]
}
""".stripMargin
val expected = JsonValueExpectedReport7_1(
"Command execution"
, List(Left(List("/bin/echo \"restore\"")))
)
(jsonMin.fromJson[JsonValueExpectedReport7_1]) must beEqualTo(Right(expected))
}
/*
Left(.vs[0](expected '{' got '[')) != Right(JsonValueExpectedReport7_1(Command execution,List(Left(List(/bin/echo "restore"))))) expected:<[Right(JsonValueExpectedReport7_1(Command execution,List(Left(List(/bin/echo "restore")))]))> but was:<[Left(.vs[0](expected '{' got '[']))>
Comparison Failure:
Expected :Right(JsonValueExpectedReport7_1(Command execution,List(Left(List(/bin/echo "restore")))))
Actual :Left(.vs[0](expected '{' got '['))
*/
"the right case" >> {
import zio.json._
val jsonMin =
"""
{
"vid": "Command execution",
"vs": [
{"id": "id", "v":"value"}
]
}
""".stripMargin
val expected = JsonValueExpectedReport7_1(
"Command execution"
, List(Right(JsonExpectedValueId7_1("id", "value")))
)
(jsonMin.fromJson[JsonValueExpectedReport7_1]) must beEqualTo(Right(expected))
}
/*
Left(.vs[0](missing fields)) != Right(JsonValueExpectedReport7_1(Command execution,List(Right(JsonExpectedValueId7_1(id,value))))) expected:<[Right(JsonValueExpectedReport7_1(Command execution,List(Right(JsonExpectedValueId7_1(id,value)))]))> but was:<[Left(.vs[0](missing fields]))>
Comparison Failure:
Expected :Right(JsonValueExpectedReport7_1(Command execution,List(Right(JsonExpectedValueId7_1(id,value)))))
Actual :Left(.vs[0](missing fields))
*/
}
//
// REMOVING encoder makes the decoder works?!?
//
@RunWith(classOf[JUnitRunner])
class ReproduceErrorTest extends Specification {
final case class JsonExpectedValueId7_1(id: String, v: String)
final case class JsonValueExpectedReport7_1(
vid: String
, vs: List[Either[List[String],JsonExpectedValueId7_1]]
)
implicit lazy val codecJsonExpectedValueId7_1: JsonDecoder[JsonExpectedValueId7_1] = DeriveJsonDecoder.gen
implicit lazy val codecJsonEitherValue: JsonDecoder[Either[List[String],JsonExpectedValueId7_1]] = {
// invariance is complicated
def toRight(x: JsonExpectedValueId7_1): Either[List[String],JsonExpectedValueId7_1] = Right(x)
def toLeft(x: List[String]): Either[List[String],JsonExpectedValueId7_1] = Left(x)
JsonDecoder[List[String]].map(toLeft).orElse(codecJsonExpectedValueId7_1.map(toRight))
}
implicit lazy val codecJsonValueExpectedReport7_1: JsonDecoder[JsonValueExpectedReport7_1] = DeriveJsonDecoder.gen
sequential
"the left case" >> {
import zio.json._
val jsonMin =
"""
{
"vid": "Command execution",
"vs": [
[ "/bin/echo \"restore\"" ]
]
}
""".stripMargin
val expected = JsonValueExpectedReport7_1(
"Command execution"
, List(Left(List("/bin/echo \"restore\"")))
)
(jsonMin.fromJson[JsonValueExpectedReport7_1]) must beEqualTo(Right(expected))
}
// SUCCESS
"the right case" >> {
import zio.json._
val jsonMin =
"""
{
"vid": "Command execution",
"vs": [
{"id": "id", "v":"value"}
]
}
""".stripMargin
val expected = JsonValueExpectedReport7_1(
"Command execution"
, List(Right(JsonExpectedValueId7_1("id", "value")))
)
(jsonMin.fromJson[JsonValueExpectedReport7_1]) must beEqualTo(Right(expected))
}
// SUCCESS
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment