zio-schema icon indicating copy to clipboard operation
zio-schema copied to clipboard

Encoding Decoding Map to JSON

Open carlos-verdes opened this issue 1 year ago • 10 comments

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: image

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
)

carlos-verdes avatar Nov 29 '22 08:11 carlos-verdes

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

carlos-verdes avatar Nov 29 '22 11:11 carlos-verdes

Created some tests to reproduce these issues, please let me know if you agree with this Spec before I try to fix the code

image

image

carlos-verdes avatar Nov 29 '22 12:11 carlos-verdes

@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)

carlos-verdes avatar Nov 29 '22 17:11 carlos-verdes

@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

carlos-verdes avatar Mar 29 '23 13:03 carlos-verdes

/bounty $75

jdegoes avatar Jan 30 '24 08:01 jdegoes

💎 $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 bountyShare on socials

Attempt Started (GMT+0) Solution
🔴 @Samankhalid01 Feb 6, 2024, 7:10:35 PM WIP

algora-pbc[bot] avatar Jan 30 '24 08:01 algora-pbc[bot]

I think this was fixed on previous PR @jdegoes

carlos-verdes avatar Jan 31 '24 17:01 carlos-verdes

/attempt #447

Options

Samankhalid01 avatar Feb 06 '24 19:02 Samankhalid01

@Samankhalid01: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏

algora-pbc[bot] avatar Feb 13 '24 19:02 algora-pbc[bot]

The bounty is up for grabs! Everyone is welcome to /attempt #447 🙌

algora-pbc[bot] avatar Feb 20 '24 19:02 algora-pbc[bot]