Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does this support enums as keys in a map? #5

Closed
blanchet4forte opened this issue May 11, 2022 · 9 comments
Closed

Does this support enums as keys in a map? #5

blanchet4forte opened this issue May 11, 2022 · 9 comments
Assignees

Comments

@blanchet4forte
Copy link

blanchet4forte commented May 11, 2022

Title says it all. I'm currently using enumeratum with PlayJson and Jackson using a custom Jackson setup using @JsonValue and @JsonCreator annotations to get Jackson to recognize them. But we are having issues with deserializing enums as keys in a map. The serialization works as expected but the keys always come back as strings instead of the enum type when deserializing with Jackson. PlayJson works fine.

Everything else seems to work fine except this one scenario. Does your library support this?

Thanks.

@pjfanning
Copy link
Owner

pjfanning commented May 11, 2022

Doesn't appear to work - see #6

This project has little or no uptake. I don't use it myself. I am currently travelling and may look at this when I get back - but to be frank, I prefer users who contribute fixes to users who ask questions without even spending 5 minutes trying it for themselves. Open source is about collaboration not about unpaid developers providing free work to paid developers.

@pjfanning
Copy link
Owner

map key deserialization is a mine field - https://www.baeldung.com/jackson-map highlights some jackson annotation that allow some control over the process

there are numerous other Scala json deserializers - maybe Circe, zio-json, jsoniter-scala are worth trying - but Map[A, B] is always a messy deserialization target

@blanchet4forte
Copy link
Author

I apologize. I didn't mean to imply we were using your library and running into this issue. I was simply trying to find out if this was a supported scenario in your library to see if it was something we could use or not. I created an issue because there is no discussions section for this repository.

My investigation in our own setup leads me to believe this may be an issue in Jackson itself. As I've tried creating both custom StdSerializer/StdDeserializer as well as a custom KeyDeserializer and neither seems to get it so Jackson does the correct thing.

@pjfanning
Copy link
Owner

pjfanning commented May 11, 2022

jackson-databind does appear to have limitations on what can be used as a map key - see FasterXML/jackson-databind#3283 for an example issue

@blanchet4forte
Copy link
Author

Thanks for the links. It's strange to me that I have the PlayJson side working fine -- since PlayJson is built on top of Jackson. Makes me wonder what voodoo they are doing in PlayJson to support this 🤔

@pjfanning
Copy link
Owner

Thanks for the links. It's strange to me that I have the PlayJson side working fine -- since PlayJson is built on top of Jackson. Makes me wonder what voodoo they are doing in PlayJson to support this 🤔

play-json only uses the core json parser of jackson - basically to construct JSON AST - the serde from/to Scala classes is specific to play-json. play-json does not use the jackson scala or enumeratum modules.

play-json uses Scala macros to do a lot of the type introspection - while Jackson relies on Java reflection and this suffers due to type erasure

@blanchet4forte
Copy link
Author

I haven't had time to look into this more. But one thing I have thought about is whether or not it is correct for this to accept Options for Keys. I need to look to see what Play Json does in this case. But it would seem incorrect to me, especially if the Option is None.

@pjfanning
Copy link
Owner

v2.13.3 is released

@pjfanning
Copy link
Owner

I haven't had time to look into this more. But one thing I have thought about is whether or not it is correct for this to accept Options for Keys. I need to look to see what Play Json does in this case. But it would seem incorrect to me, especially if the Option is None.

The current code does not support using Option of Enum as a map key type. I'd prefer to treat that as a separate issue. If you feel strongly that this needs to be supported, raise a new issue. I don't know what value would represent the None value. - it can't really be an empty string when acting as field name in the serialized JSON.

This is a sample test that fails in current code

    "deserialize map with Option of enum key" in {
      val mapper = JsonMapper.builder().addModule(DefaultScalaModule).addModule(EnumeratumModule).build()
      val colorMap = Map(Some(Color.Blue) -> "blue", None -> "none")
      val colorJson = mapper.writeValueAsString(colorMap)
      val colorMap2 = mapper.readValue(colorJson, new TypeReference[Map[Option[Color], String]]{})
      colorMap2 should have size 2
      colorMap2(Some(Color.Blue)) shouldEqual "blue"
      colorMap2(None) shouldEqual "none"
    }

Fails with

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [reference type, class scala.Option<com.github.pjfanning.enumeratum.Color><[simple type, class com.github.pjfanning.enumeratum.Color]>]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants