Skip to content

Conversation

@arnegoeteyn
Copy link

I've encountered an issue with the typing of discriminators. To illustrate the issue here's a minimum reproducible example.

openapi: 3.0.0

paths:
  /example:
    post:
      responses:
        400:
          content:
            application/json:
              schema:
                oneof:
                  - $ref: "#/components/schemas/apple"
                  - $ref: "#/components/schemas/banana"
                  - $ref: "#/components/schemas/orange"
                discriminator:
                  propertyname: code
                  mapping:
                    1: "#/components/schemas/apple"
                    2: "#/components/schemas/banana"
                    3: "#/components/schemas/orange"

components:
  schemas:
    apple:
      type: object
      required: [code, fruit]
      properties:
        code:
          const: 1
          type: integer
        fruit:
          const: apple
          type: string
    banana:
      type: object
      required: [code, fruit]
      properties:
        code:
          const: 2
          type: integer
        fruit:
          const: banana
          type: string
    orange:
      type: object
      required: [code, fruit]
      properties:
        code:
          const: 3
          type: integer
        fruit:
          const: orange
          type: string

Ogen now generates an encodeFields method on ExamplePostBadRequest. It will encode the field code as a string while the api specification says it will be an integer.

func (s ExamplePostBadRequest) encodeFields(e *jx.Encoder) {
	switch s.Type {
	case AppleExamplePostBadRequest:
		e.FieldStart("code")
		e.Str("1")
		{
			s := s.Apple
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	case BananaExamplePostBadRequest:
		e.FieldStart("code")
		e.Str("2")
		{
			s := s.Banana
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	case OrangeExamplePostBadRequest:
		e.FieldStart("code")
		e.Str("3")
		{
			s := s.Orange
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	}
}

This PR creates a fix for this by testing if the discriminator can be parsed as an integer. If that is the case a slightly altered template is used and the following code is generated.

func (s ExamplePostBadRequest) encodeFields(e *jx.Encoder) {
	switch s.Type {
	case AppleExamplePostBadRequest:
		e.FieldStart("code")
		e.Int(1)
		{
			s := s.Apple
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	case BananaExamplePostBadRequest:
		e.FieldStart("code")
		e.Int(2)
		{
			s := s.Banana
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	case OrangeExamplePostBadRequest:
		e.FieldStart("code")
		e.Int(3)
		{
			s := s.Orange
			{
				e.FieldStart("fruit")
				e.Str(s.Fruit)
			}
		}
	}
}

I suppose this is a bit of a naive fix, what if we want to use 3 but need it to be of a string type. However this completely fixes my issue.

If this PR is good as is it would be great if it could be merged. If this solution is no good it would be great if someone could nudge me in the right direction to tackle this issue.

@ernado
Copy link
Member

ernado commented Jan 5, 2026

As far as I understood PR, this approach can conflict with case of having string integers, e.g.
{ discriminator: "200" }.

More safe approach is to use information about types, i.e. wheter discriminator type is type: integer.

@arnegoeteyn arnegoeteyn force-pushed the numeric-discriminator branch from 36af4e9 to 83f99a6 Compare January 6, 2026 12:36
@arnegoeteyn
Copy link
Author

I've updated the approach of this PR to check the actual type of the discriminator. It will keep the old behavior of encoding a string in all cases except if the discriminator is defined as an integer in the specification.

@arnegoeteyn arnegoeteyn force-pushed the numeric-discriminator branch from 83f99a6 to 370dc37 Compare January 6, 2026 13:01
Attaches the type of the discriminator field to a SumMap. This type can
then be used to determine if the discriminator field should be encoded
as an integer of as a string.
@arnegoeteyn arnegoeteyn force-pushed the numeric-discriminator branch from 370dc37 to 5760071 Compare January 15, 2026 13:20
@frederikdesmedt
Copy link

We also ran into this issue and can confirm that this fixed it 👍

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.

3 participants