Fix enum serialization (names instead of toString), value enums in kebs-baklava, add Seq columns to kebs-slick - #593
Merged
Conversation
Enum formats, column types and params serialized entries with `toString`, which differs from the entry name for Enumeratum enums with a custom `entryName` or a casing mixin (e.g. `EnumEntry.Uppercase`). - use `EnumLike.getName` in spray-json, play-json, circe, slick, doobie, http4s and baklava, and names in enum error messages - look up case-insensitive names by name in `EnumLike` - add `EnumLike.apply` / `ValueEnumLike.apply`, used by all derivations: lookup maps are computed once and `values` keeps declaration order - abort Enumeratum derivation for types without a companion (e.g. a case object) - add `Seq` column types: for enums by default, for value classes and instance types in the opt-in `KebsSeqImplicits` Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mQaz4h7dYNSiY6ZFvg1fs
Contributor
|
This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mQaz4h7dYNSiY6ZFvg1fs
Value enum instances were built on the value type from instances of the enum type (e.g. `Schema[Int]` from `Schema[Level]`), so value enums were documented by baklava's generic derivation as string enums of entry names and couldn't be used as query, path or header params. They are now built on the enum type from instances of the value type, listing entry values. Value class and instance converter schemas also keep the underlying `additionalPropertiesSchema`, as baklava's own wrapper schemas do. Add the first tests for kebs-baklava, covering all its instances. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mQaz4h7dYNSiY6ZFvg1fs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Enum support serialized entries with
toString. For Enumeratum enums that's not the entry's name wheneverentryNameis overridden or a casing mixin likeEnumEntry.Uppercase/EnumEntry.Snakecaseis used. So an entry declared ascase object Active extends Status { override val entryName = "is-active" }was written as"Active"to JSON and to the database, and couldn't be read back. No existing test used a customentryName, so this went unnoticed. It came up while migrating a large codebase from kebs 1.9.7, where JSON and DB values would have silently changed.While fixing baklava's enum params, I also found that its value enum support is inverted, so this PR fixes that too and adds the module's first tests.
Enum names
getName. Covers spray-json, play-json, circe (the upper/lowercase variants; its default encoder already did this), slick (enum,Listand hstore mappings, all casing variants), doobie, http4s path/query params, and baklava params/schemas (resolving thetodo use getNamecomments). Enum deserialization error messages now list names too, so they showis-activerather thanActive.EnumLikeignore-case lookups use names:withNameIgnoreCase,withNameIgnoreCaseOption,valueOfIgnoreCase.EnumLike.apply(entries, name)andValueEnumLike.apply(entries), used by all derivations (Enumeratum on Scala 2 and 3,scala.Enumeration, Scala 3enums):valuesToNamesMapand the reverse map on every call, e.g. on every JSON read or write.valueskeeps declaration order. Previously it came from aMap's keys, sofromOrdinal/indexOfwere wrong for enums with more than 4 entries.Value enums in kebs-baklava
The value enum schema and params were built the wrong way round.
valueEnumLikeSchema[T, V <: ValueEnumLikeEntry[T]]produced aSchema[T]for the value type (e.g.Int) and needed aSchema[V]of the enum. The params did the same (ToQueryParam[Int]built fromToQueryParam[Level]). The schema also listed entries'toStringinstead of their values. For a value enumLevel(value: Int)withLow(1)andHigh(10), which kebs JSON formats send as1/10:Levelas a string enum"Low" | "High".The instances are now keyed on the enum type:
Schema[E]built fromSchema[V](e.g.integer/int32), withenumset to the entries' values;ToQueryParam[E]/ToPathParam[E]/ToHeader[E]built from the value type's instances; header parsing goes back throughwithValueOption.The erased signatures are unchanged, so MiMa is clean. The old instances couldn't be used, so no working code depends on them.
The value class and instance converter schemas now also keep the underlying
additionalPropertiesSchema, as baklava's own wrapper schemas do. Before, a value class wrapping aMaplost its value schema.Seqcolumn types in kebs-slickStored like
Listcolumns (kebs 1.x supported them):KebsEnumImplicitsand the casing variants;KebsSeqImplicits. It's opt-in because on Scala 3 these instances break type inference of slick-pg array extension methods (@>) onListcolumns;SlickPgArrayTests/SlickPgHstoreTestsfail on Scala 3 with them in the default traits.Tests
entryNameand anEnumEntry.Uppercaseenum:EnumeratumEntryNameTest: names, lookups, declaration order, and no instance for a case object's type;SlickEnumEntryNameTests: column,List/Seqand hstore mappings.Seqcolumns inSlickPgArrayColumnTypeTests.default,descriptionandadditionalPropertiesSchema.Against the code without the fix, the new Enumeratum tests fail (3 of 4).
Verified locally
CI=true(fatal warnings);mimaReportBinaryIssuesis clean against 2.1.6 and 2.2.1;Behaviour changes
entryNamenow serialize with that name (the documented behaviour) instead oftoString. Scala 3enums andscala.Enumerationare unaffected, since their name istoString.