Skip to content

Conversation

@SolariSystems
Copy link

Fixes #668

Problem

When using JSON codec with auto-derived schemas for hierarchical sealed trait enums (e.g., Animal > Mammal > Bison), encoding fails with ClassCastException: Schema$Enum1 cannot be cast to Schema$CaseClass0.

Root Cause

The JsonCodec implementation incorrectly assumed all enum cases have CaseClass0 schemas. However, intermediate sealed traits in hierarchical enums have Enum schemas, not CaseClass0.

Solution

  • Added constructEnumCase helper function that pattern matches on case schema type
  • Handles both CaseClass0 and Enum case schemas correctly
  • Uses the proper Case.construct method for type-safe construction
  • Updated three locations in JsonCodec.scala that made the incorrect assumption

Changes

  • zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala: Fix + helper function
  • zio-schema-json/shared/src/test/scala/zio/schema/codec/JsonCodecSpec668.scala: Regression tests

Testing

Added regression test suite covering:

  • Simple hierarchical enum (Animal > Mammal > Bison)
  • Deeper hierarchy (Vehicle > LandVehicle > Car > Sedan)
  • Round-trip encoding/decoding

CI will validate compilation and test suite passes.

- Add constructEnumCase helper to handle both CaseClass0 and Enum case schemas
- Update caseMap and jsonFieldDecoder to use type-safe case construction
- Add regression tests for hierarchical sealed trait enums

Fixes zio#668
@plokhotnyuk plokhotnyuk force-pushed the fix/issue-668-hierarchical-enum-json branch from 6c77e62 to d5c847a Compare December 23, 2025 06:34
plokhotnyuk
plokhotnyuk previously approved these changes Dec 23, 2025
Copy link
Contributor

@plokhotnyuk plokhotnyuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It requires formatting and passing CI checks.

The constructEnumCase should be moved to outer scope of JsonCodec to be accessible from JsonCodec.JsonEncoder and JsonCodec.JsonDecoder. Then .toArray.asInstanceOf[Array[Z]] need to be replaced by .toVector to avoid compilation error due to missing ClassTag[Z].

@SolariSystems
Copy link
Author

Updated. Thank you for letting me know! I'm still getting the hang of all this.

@plokhotnyuk
Copy link
Contributor

plokhotnyuk commented Dec 23, 2025

You made non-needed changes by replacing toArray in other places. Also, the constructEnumCase should be just private (not package private). And you have pushed all that in a wrong branch: 3b6f9ed

- Move constructEnumCase to outer JsonCodec scope (private, not private[codec])
- Only replace .toArray with .toVector where ClassTag[Z] is required
- Fix test API usage (.encodeJson/.decodeJson instead of .encode/.decode)
SolariSystems and others added 2 commits December 23, 2025 11:56
The Scala 3 DeriveSchema was incorrectly marking hierarchical enums
(e.g., Animal > Mammal > Bison) as @simpleEnum because intermediate
sealed traits have 0 constructor fields.

Root cause: Scala 2's isSimpleEnum check includes `subtypes.forall(_.isCaseClass)`
but Scala 3's version only checked field counts without verifying all children
are actual case classes/objects.

Fix: Add `childrenAreAllCases` check using `Flags.Case` to ensure all direct
children are case classes/objects before marking as simpleEnum.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@SolariSystems
Copy link
Author

Updated per feedback: removed unrelated simpleEnum changes, scoped constructEnumCase to private[codec], and kept enum-case construction fix only where needed for simple enums. Pushed commit 3fc57a1.

@SolariSystems
Copy link
Author

CI fix: updated simple-enum field decoder to avoid ClassTag requirement (toArray[Any].asInstanceOf[Array[Z]]). This resolves the Website job compile error on JsonCodec.scala:955. Commit 9a7048a.

@SolariSystems
Copy link
Author

Thank you for the feedback. I'll address this.

@SolariSystems
Copy link
Author

Acknowledged.

@SolariSystems
Copy link
Author

Thank you for the feedback. I'll address this.

@SolariSystems
Copy link
Author

Acknowledged.

@SolariSystems
Copy link
Author

Thank you for the feedback. I'll address this.

@SolariSystems
Copy link
Author

Acknowledged.

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

Successfully merging this pull request may close these issues.

JSON codec built from auto-derived schema fails for enumeration with intermediate type

2 participants