-
Notifications
You must be signed in to change notification settings - Fork 115
Replace JsonError and DynamicValueError with SchemaError #889
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
Replace JsonError and DynamicValueError with SchemaError #889
Conversation
This PR unifies all error types under SchemaError, ensuring that when combining JsonSelection or DynamicValueSelection via ++, errors are properly aggregated instead of being lost. ## Changes ### SchemaError enhancements - Add SchemaError.Message case class for simple message+path errors - Add SchemaError.message(details, path) constructor - Add SchemaError.apply(details) convenience constructor - Add atField, atIndex, atKey, atCase methods that prepend to all errors - Add remapSource helper for updating paths in error aggregation ### JsonSelection & DynamicValueSelection - Replace Either[JsonError, ...] with Either[SchemaError, ...] - Replace Either[DynamicValueError, ...] with Either[SchemaError, ...] - Update ++ operator to aggregate errors when both sides fail - Previously: only first error was kept - Now: both errors are aggregated into a single SchemaError ### Files deleted - JsonError.scala - replaced by SchemaError - DynamicValueError.scala - replaced by SchemaError - DynamicValueErrorSpec.scala - replaced by SchemaErrorPathSpec.scala ### Test updates - Add SchemaErrorPathSpec with comprehensive tests for path methods - Update all tests using JsonError/DynamicValueError to use SchemaError - Add tests verifying error aggregation in ++ operator Closes #868 Amp-Thread-ID: https://ampcode.com/threads/T-019c078a-eb23-745d-94ed-d97ec21956d8 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR unifies JSON and DynamicValue error handling under SchemaError, so that selection and decoding operations can aggregate multiple errors (with paths) instead of losing detail via string concatenation.
Changes:
- Replace
JsonError/DynamicValueErrorwithSchemaErroracross JSON and DynamicValue selection, navigation, and decoding APIs, includingJsonSelection,DynamicValueSelection,Json,DynamicValue, andJsonDecoder. - Extend
SchemaErrorwith message-based errors, path-prepend helpers (atField,atIndex,atKey,atCase), and a source-remapping helper so aggregated errors keep accurate paths. - Update and extend tests: add
SchemaErrorPathSpec, adapt JSON/DynamicValue selection specs toSchemaError, and add dedicated tests for error aggregation (++) and exception behavior, while removing the now-obsolete error classes and specs.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
schema/shared/src/main/scala/zio/blocks/schema/json/JsonSelection.scala |
Switches JsonSelection to Either[SchemaError, Vector[Json]] and updates combinators (including ++) and extraction methods to propagate and aggregate SchemaErrors. |
schema/shared/src/main/scala/zio/blocks/schema/DynamicValueSelection.scala |
Migrates DynamicValueSelection to Either[SchemaError, Chunk[DynamicValue]] and updates ++, type-directed extraction, and unsafe helpers to work with SchemaError aggregation. |
schema/shared/src/main/scala/zio/blocks/schema/SchemaError.scala |
Adds SchemaError.Message, convenience constructors (message, apply(String)), path-prepend methods for all aggregated errors, and a remapSource helper used by those methods. |
schema/shared/src/main/scala/zio/blocks/schema/json/JsonDecoder.scala |
Changes all decoder signatures to return Either[SchemaError, A], threads SchemaError through collection and composite decoders, and forwards schema-derived codec errors as SchemaError; note: in eitherDecoder, the Right-branch still tags errors with .atField("Left"), which mislabels the error path and should use "Right" instead. |
schema/shared/src/main/scala/zio/blocks/schema/json/Json.scala |
Replaces JsonError with SchemaError for navigation (get), path-based mutation (modifyOrFail, setOrFail, deleteOrFail, insertOrFail), folds, parses, and reconstruction helpers, ensuring codec errors are surfaced as SchemaError. |
schema/shared/src/main/scala/zio/blocks/schema/DynamicValue.scala |
Replaces DynamicValueError with SchemaError throughout navigation, path-based updates, folds, and KV reconstruction, using SchemaError.message(..., path) to record precise paths. |
schema/shared/src/main/scala/zio/blocks/schema/json/JsonError.scala |
Deleted; functionality is replaced by SchemaError.Message and the enriched SchemaError API. |
schema/shared/src/main/scala/zio/blocks/schema/DynamicValueError.scala |
Deleted; replaced by SchemaError.Message and unified SchemaError handling for DynamicValue operations. |
schema/shared/src/test/scala/zio/blocks/schema/json/JsonSpec.scala |
Updates tests from JsonError to SchemaError, adjusts path assertions to the new SchemaError shape, adds suites validating SchemaError exception behavior and ++ aggregation in the JSON context. |
schema/shared/src/test/scala/zio/blocks/schema/json/JsonSelectionSpec.scala |
Migrates selection tests to SchemaError, including new tests verifying ++ aggregates errors and that type-directed extraction methods (as, unwrap, unwrapAll) now use SchemaError. |
schema/shared/src/test/scala/zio/blocks/schema/DynamicValueSelectionSpec.scala |
Adapts DynamicValueSelection tests to SchemaError, adds coverage for error aggregation in ++, and keeps unsafe methods asserting that SchemaError is thrown. |
schema/shared/src/test/scala/zio/blocks/schema/DynamicValueSpec.scala |
Switches fold failure tests from DynamicValueError to SchemaError to match the new API. |
schema/shared/src/test/scala/zio/blocks/schema/SchemaErrorPathSpec.scala |
New spec comprehensively testing SchemaError message formatting, ++ aggregation, and path-prepend behavior (atField, atIndex, atKey, atCase) across single and aggregated errors. |
schema/shared/src/test/scala/zio/blocks/schema/DynamicValueErrorSpec.scala |
Removed; its coverage is replaced by SchemaErrorPathSpec and the DynamicValue/selection tests that now validate SchemaError behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
schema/shared/src/main/scala/zio/blocks/schema/json/JsonDecoder.scala
Outdated
Show resolved
Hide resolved
When decoding fails in the Right case of an Either, the error path should indicate .Right, not .Left. This was a copy-paste error. Amp-Thread-ID: https://ampcode.com/threads/T-019c078a-eb23-745d-94ed-d97ec21956d8 Co-authored-by: Amp <amp@ampcode.com>
Left/Right are cases of Either (a sum type), not fields of a record. Similarly, Some is a case of Option. This fixes the semantic error in error path reporting for: - eitherDecoder: Left/Right cases now use atCase - optionDecoder: Some case now uses atCase when inner decoder fails The atCase method properly represents navigation into a variant/sum type, while atField represents navigation into a record/product type. Amp-Thread-ID: https://ampcode.com/threads/T-019c078a-eb23-745d-94ed-d97ec21956d8 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
This PR unifies all error types under
SchemaError, ensuring that when combiningJsonSelectionorDynamicValueSelectionvia++, errors are properly aggregated instead of being lost.Closes #868
Problem
When combining two selections that both contain errors using
++, the previous implementation would:JsonError: Concatenate messages with;separator, losing path info from the second errorDynamicValueError: Same string concatenation issueSolution
Replace both
JsonErrorandDynamicValueErrorwithSchemaError, which already supports error aggregation via its++operator that maintains a list ofSingleerrors.Changes
SchemaError enhancements
SchemaError.Messagecase class for simple message+path errorsSchemaError.message(details, path)constructorSchemaError.apply(details)convenience constructoratField,atIndex,atKey,atCasemethods that prepend paths to all errorsremapSourcehelper for updating paths in error aggregationJsonSelection & DynamicValueSelection
Either[JsonError, ...]withEither[SchemaError, ...]Either[DynamicValueError, ...]withEither[SchemaError, ...]++operator to aggregate errors when both sides failFiles deleted
JsonError.scala- replaced bySchemaErrorDynamicValueError.scala- replaced bySchemaErrorDynamicValueErrorSpec.scala- replaced bySchemaErrorPathSpec.scalaTest updates
SchemaErrorPathSpecwith comprehensive tests for path methodsJsonError/DynamicValueErrorto useSchemaError++operatorTesting