swagger-api / swagger-api/swagger-codegen

[Swift3] Inheritance decoding with discriminator fails (2.3 branch)

Open
#5,812 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Client: Swift Feature: Composition / Inheritance Issue: Bug
Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

When the client tries to decode a response to an object that has inheritance, decoding fails because of a casting error. We get a mismatched type error because it cannot cast Decoded<File> to Decoded<Resource>

Swagger-codegen version

2.3.0 branch

Swagger declaration file content or url

This is the structure of the objects in the swagger definitions:

  Resource:
    type: object
    description: Common meta data for resources (files and directories)
    discriminator: resource_type
    properties:
      id:
        description: The unique identifier of this file
        type: string
        readOnly: true
      resource_type:
        type: string
        enum: [File, Directory]
        readOnly: true
        example: File
  File:
    type: object
    description: Meta data of a file. Use the url property to access the actual file
    allOf:
      - $ref: '#/definitions/Resource'
      - type: object
        properties: <snip>
  Directory:
    type: object
    description: Meta data of a directory
    allOf:
      - $ref: '#/definitions/Resource'
      - type: object
        properties: <snip>

This is the code in Models.swift that does the decoding:

 // Decoder for Resource
        Decoders.addDecoder(clazz: Resource.self) { (source: AnyObject, instance: AnyObject?) -> Decoded<Resource> in
            if let sourceDictionary = source as? [AnyHashable: Any] {
                // Check discriminator to support inheritance
                if let discriminator = sourceDictionary["resource_type"] as? String, instance == nil && discriminator != "Resource"{
                    return Decoders.decode(clazz: Resource.self, discriminator: discriminator, source: source)
                }
  //etc

And it fails in the decode function defined in Models.mustache line 70
https://github.com/swagger-api/swagger-codegen/blob/2.3.0/modules/swagger-codegen/src/main/resources/swift3/Models.mustache#L70

I'm not a very experienced with Swift so I tried multiple ways of casting the type, or somehow enforcing that the type T extends some other type, but none of it worked, in the end you simply cannot cast Decoded<File> to Decoded<Resource>

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

Start with the generated Models.swift decoder shown in the issue and the decode function in modules/swagger-codegen/src/main/resources/swift3/Models.mustache at line 70. Reproduce the failure using the Resource, File, and Directory inheritance definitions with the resource_type discriminator. Done means decoding the inherited response no longer fails when the result is handled as Decoded.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
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.