zio-schema
zio-schema copied to clipboard
Encoding Decoding Map to JSON
How to reproduce, create a case class with an optional field of type Map:
case class ServerVersion(
server: String,
license: String,
version: String,
details: Map[String, String] = Map.empty
)
given Schema[ServerVersion] = DeriveSchema.gen[ServerVersion]
Expected test to pass:
test("Encode/Decode ServerInfo from json using schema") {
for
_ <- ZIO.unit
json = """{ "server": "arango", "license": "community", "version": "3.10.1"}"""
chunks = Chunk.fromArray(json.getBytes)
serverInfo <- ZIO.fromEither(
JsonCodec.decode[ServerVersion](given_Schema_ServerVersion)(chunks)
)
yield assertTrue(
serverInfo == ServerVersion("arango", "community", "3.10.1")
)
}
Error: the field details is decoded as Map("" -> "" )
instead of Map.empty
:
I tried also with next annotations:
import zio.schema.annotation.{fieldDefaultValue, optionalField}
case class ServerVersion(
server: String,
license: String,
version: String,
@optionalField
@fieldDefaultValue[Map[String, String]](Map.empty)
details: Map[String, String] = Map.empty
)
I checked the Spec and I see Map is encoded as a sequence of tuples like:
[
{"key1": value1},
{"key2": value2}
]
However the expectation for me is:
{
"key1": value1,
"key2": value2
}
I think we should change the full implementation of Map encoder/decoder not just the default values
Created some tests to reproduce these issues, please let me know if you agree with this Spec before I try to fix the code
@jdegoes @thinkharderdev @devsprint @tusharmath
This is a big problem to use in any API, I have to receive/pass very often Map[String, String] for extra configuration (for example if you use Spark) and it's really weird that is mapped to json [] instead of {}
I implemented a library for ArangoDB using zio-http and zio-json for serialization and I'm now trying to support zio-schema on top of that (so you can use ArangoDB with any type that has an Schema, and I plan to do dynamic graph queries that bring more than 1 entity just from the Schema abstraction)
@jdegoes @thinkharderdev @devsprint @tusharmath
I finally had time to implement the full code, to start I only apply the new encoder/decoder when the Map has String as key As I created a new PR this issue is reopened
We can apply more improvements on next PRs if you think is worth it:
- apply similar logic for any key that is primitive converting the key into String (
encoder.contramap(_.toString)
) - create a new annotation
/bounty $75
💎 $75 bounty created by ZIO
🙋 If you start working on this, comment /attempt #447
along with your implementation plan
👉 To claim this bounty, submit a pull request that includes the text /claim #447
somewhere in its body
📝 Before proceeding, please make sure you can receive payouts in your country
💵 Payment arrives in your account 2-5 days after the bounty is rewarded
💯 You keep 100% of the bounty award
🙏 Thank you for contributing to zio/zio-schema!
👉 Add a bounty • Share on socials
Attempt | Started (GMT+0) | Solution |
---|---|---|
🔴 @Samankhalid01 | Feb 6, 2024, 7:10:35 PM | WIP |
I think this was fixed on previous PR @jdegoes
@Samankhalid01: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏
The bounty is up for grabs! Everyone is welcome to /attempt #447
🙌