pjfanning / jackson-module-scala3-enum

Jackson support for Scala3 enums
Apache License 2.0
6 stars 3 forks source link

[Feature request] Use `@JsonValue` annotation #2

Open caarmen opened 2 years ago

caarmen commented 2 years ago

Currently, the EnumSerializerModule serializes enums by using their toString :

def serialize(value: Enum, jgen: JsonGenerator, provider: SerializerProvider): Unit =
  provider.defaultSerializeValue(value.toString, jgen)

It would be nice to look for a field with a @JsonValue annotation, and use that instead of toString(), if it exists.

Example use case:

enum PartOfSpeech(@JsonValue val modelName: String):

  case NOUN extends PartOfSpeech("noun")
  case ADJECTIVE extends PartOfSpeech("adjective")
  case ADVERB extends PartOfSpeech("adverb")
  case VERB extends PartOfSpeech("verb")
  case UNKNOWN extends PartOfSpeech("unknown")

end PartOfSpeech

I'd like to see noun instead of NOUN in the json.

For now, my workaround is to override toString:

override def toString: String = modelName

This workaround seems to work just fine. I thought it might be a nice bonus to be able to use the @JsonValue annotation though.

⚠️ This requested feature may not work in scala3 if the annotation is on a constructor parameter, because of this issue: https://github.com/FasterXML/jackson-module-scala/issues/532

pjfanning commented 2 years ago

@caarmen I had a quick look and the Java annotation seems to be missing on the class. Seems like this might be related to that dotty issue you linked to FasterXML/jackson-module-scala#532

pjfanning commented 2 years ago

@caarmen I added https://github.com/lampepfl/dotty/issues/12492#issuecomment-986226294 - but while that issue is similar to this, I think it is different. That issue relates to the @getter being ignored (Scala 3 does not not ignore the @JsonValue when the @getter is removed but that changes the meaning of the @JsonValue annotation so it doesn't work).

In this case, there is an annotation on the enum class and Scala 3 seems to ignore it regardless of the @getter annotation.

pjfanning commented 2 years ago

actually, I think the existing dotty issue might fix this issue - but you will need

@(JsonValue @getter)

instead of just @JsonValue

The core jackson-databind does not seem to support @JsonValue on fields - that you seem to need to have the annotation on a method and the @getter meta annotation means the annotation gets added to the getter method instead of the field (both called after the field name).

pjfanning commented 2 years ago

If you use @JsonValue - you need to add a @JsonCreator annotation to support the deserialization case - see https://stackoverflow.com/questions/57896888/jackson-jsonvalue-annotated-field-cannot-be-deserialized