OpenAPITools / OpenAPITools/openapi-generator

[BUG] Error during deserialization for elements with discriminator and mapping type name

Open
#14,562 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

There is an exception during the deseralization of an element defined with a discriminator and a mapping type name, in the read(JsonReader) method of the generated model java class.

Failed deserialization for MetadataFieldAny: 5 classes match result, expected 1.
JSON: {"type":"int","value":1}

Multiple match was found while a discriminator was provided.

openapi-generator version

6.2.1

OpenAPI declaration file content or url
    MetadataField_Any:
      description: metadata field
      oneOf:
      - $ref: '#/components/schemas/BoolMeta'
      - $ref: '#/components/schemas/DateTimeMeta'
      - $ref: '#/components/schemas/DoubleMeta'
      - $ref: '#/components/schemas/IntMeta'
      - $ref: '#/components/schemas/MultipleDateTimeMeta'
      - $ref: '#/components/schemas/MultipleDoubleMeta'
      - $ref: '#/components/schemas/MultipleIntMeta'
      - $ref: '#/components/schemas/MultipleStringMeta'
      - $ref: '#/components/schemas/StringMeta'
      discriminator:
        propertyName: type
        mapping:
          bool: '#/components/schemas/BoolMeta'
          datetime: '#/components/schemas/DateTimeMeta'
          double: '#/components/schemas/DoubleMeta'
          int: '#/components/schemas/IntMeta'
          multidatetime: '#/components/schemas/MultipleDateTimeMeta'
          multidouble: '#/components/schemas/MultipleDoubleMeta'
          multiint: '#/components/schemas/MultipleIntMeta'
          multistring: '#/components/schemas/MultipleStringMeta'
          string: '#/components/schemas/StringMeta'

    BoolMeta:
      required:
      - value
      - type
      type: object
      properties:
        value:
          type: boolean
        type:
          type: string

    DateTimeMeta:
      required:
      - value
      - type
      type: object
      properties:
        value:
          type: string
          format: date-time
        type:
          type: string

    DoubleMeta:
      required:
      - value
      - type
      type: object
      properties:
        value:
          type: number
          format: double
        type:
          type: string

    IntMeta:
      required:
      - value
      - type
      type: object
      properties:
        value:
          type: integer
          format: int32
        type:
          type: string

    ...
Generation Details

Generated with maven plugin

This is an extract of the generated read method.

@Override
public MetadataFieldAny read(JsonReader in) throws IOException {
	Object deserialized = null;
	JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject();

	int match = 0;
	ArrayList<String> errorMessages = new ArrayList<>();
	TypeAdapter actualAdapter = elementAdapter;

	// deserialize BoolMeta
	try {
		// validate the JSON object to see if any exception is thrown
		BoolMeta.validateJsonObject(jsonObject);
		actualAdapter = adapterBoolMeta;
		match++;
		log.log(Level.FINER, "Input data matches schema 'BoolMeta'");
	} catch (Exception e) {
		// deserialization failed, continue
		errorMessages.add(String.format("Deserialization for BoolMeta failed with `%s`.", e.getMessage()));
		log.log(Level.FINER, "Input data does not match schema 'BoolMeta'", e);
	}

	// deserialize DateTimeMeta
	try {
		// validate the JSON object to see if any exception is thrown
		DateTimeMeta.validateJsonObject(jsonObject);
		actualAdapter = adapterDateTimeMeta;
		match++;
		log.log(Level.FINER, "Input data matches schema 'DateTimeMeta'");
	} catch (Exception e) {
		// deserialization failed, continue
		errorMessages.add(String.format("Deserialization for DateTimeMeta failed with `%s`.", e.getMessage()));
		log.log(Level.FINER, "Input data does not match schema 'DateTimeMeta'", e);
	}

	...

	if (match == 1) {
		MetadataFieldAny ret = new MetadataFieldAny();
		ret.setActualInstance(actualAdapter.fromJsonTree(jsonObject));
		return ret;
	}

	throw new IOException(String.format("Failed deserialization for MetadataFieldAny: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString()));
}
Steps to reproduce
  1. Write an openapi file with an element with discriminator and a mapping type name
  2. Generate the code with the maven plugin
  3. Try to read the response containing the element
Related issues/PRs
Suggest a fix

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the YAML declaration and Maven plugin, then inspect the generated Java model's read(JsonReader) method shown in the report. Trace how the discriminator mapping is handled during oneOf deserialization. Done means the mapped type is selected without the multiple-match exception for the provided JSON.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.