Skip to content

Conversation

@lanej
Copy link
Contributor

@lanej lanej commented Nov 27, 2025

Summary

Adds array element type discrimination for oneOf/anyOf schemas, enabling automatic variant selection when variants differ by their array element types (e.g., string[] vs integer[]).

This feature is conservative - it only enables array element discrimination when variants also have at least one unique field by name, ensuring reliable fallback when the array field is missing or empty.

Changes

  • Add ArrayElementType and ArrayElementTypeID to UniqueFieldVariant IR metadata
  • Add getArrayElementTypeInfo() to extract element types from array type IDs
  • Update validation to allow discrimination when array element types differ AND other unique fields exist
  • Generate decoder code that peeks into arrays using d.Capture() and d.ArrIter()

Example Schema

oneOf:
  - properties:
      items: { type: array, items: { type: string } }   # string[]
      stringInfo: { type: string }                       # unique field
  - properties:
      items: { type: array, items: { type: integer } }  # integer[]
      intInfo: { type: integer }                         # unique field

Before: "type-based discrimination with same jxType" error
After: Generates working decoder that peeks at first element

Generated Code

case "items":
    if typ := d.Next(); typ != jx.Array {
        return d.Skip()
    }
    if err := d.Capture(func(d *jx.Decoder) error {
        iter, err := d.ArrIter()
        if err != nil { return err }
        if !iter.Next() {
            // Empty array - use first variant as default
            s.Type = StringArrayVariantBasicArrayResource
            return nil
        }
        switch d.Next() {
        case jx.String:
            s.Type = StringArrayVariantBasicArrayResource
        case jx.Number:
            s.Type = IntegerArrayVariantBasicArrayResource
        }
        return nil
    }); err != nil { return err }

Testing

  • Test spec: _testdata/positive/array_element_discrimination.json
  • Covers: basic primitives with fallback fields, object vs primitive arrays, mixed discrimination
  • All existing tests pass

Limitations (Future Work)

  • Nested arrays (array[array[string]] vs array[array[integer]]) - requires recursive peeking
  • Complex object arrays where both have same object type - requires field checking within objects
  • Array element discrimination is NOT allowed as sole discriminator (requires other unique fields)

🤖 Generated with Claude Code

@lanej lanej marked this pull request as ready for review November 27, 2025 21:10
@lanej lanej force-pushed the feature/array-element-discrimination branch 6 times, most recently from 05fe329 to 91cc056 Compare November 30, 2025 15:03
Enable automatic discrimination between oneOf variants that have array
fields with different element types (e.g., string[] vs integer[] vs
boolean[]).

This extends the type-based discrimination added in PR ogen-go#1584 to support
cases where variants share the same field name with array types but
differ in their element types.

Implementation:
- Add ArrayElementType and ArrayElementTypeID fields to UniqueFieldVariant
- Add getArrayElementTypeInfo() to extract element type from array type IDs
- Update validation to allow discrimination when array element types differ
- Generate decoder code that peeks into arrays using d.Capture() and
  d.ArrIter() to check first element type without consuming

Supported cases:
- Basic primitives: string[] vs integer[] vs boolean[]
- Object vs primitive: object[] vs string[]
- Mixed: array type combined with unique field discrimination

Limitations (future work):
- Nested arrays (array[array[string]] vs array[array[integer]])
- Complex object arrays (User[] vs Product[] with same object type)
@lanej lanej force-pushed the feature/array-element-discrimination branch from 91cc056 to 8b4a188 Compare November 30, 2025 15:06
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.

1 participant