Skip to content
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

Inherited property missing from child Dto but present on identical sibling Dto #3312

Open
halvorsone opened this issue Oct 1, 2019 · 9 comments

Comments

@halvorsone
Copy link

We are trying to represent a tree of logic operators with Dtos using simple inheritance.

This is essentially what our Dtos look like:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "operator")
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAndDto.class, name = "and"),
        @JsonSubTypes.Type(value = MyOrDto.class, name = "or"),
        @JsonSubTypes.Type(value = MyEqualsDto.class, name = "equals") })
public class MyBaseDto {
    public String operator;
}

public class MyEqualsDto extends MyBaseDto {
    public String field;
    public String value;
}

public class MyPartsDto extends MyBaseDto {
    public MyBaseDto[] parts;
}

public class MyAndDto extends MyPartsDto {
}

public class MyOrDto extends MyPartsDto {
}

As you can see, the MyAndDto and MyOrDto are pretty much identical.

However, the generated Schemas (via springdoc /v3/api-docs endpoint - which uses swagger core) look like this:

"MyAndDto":{
    "type":"object",
    "allOf":[
        {
            "$ref":"#/components/schemas/MyBaseDto"
        },
        {
            "type":"object",
            "properties":{
                "parts":{
                    "type":"array",
                    "items":{
                        "$ref":"#/components/schemas/MyBaseDto"
                    }
                }
            }
        }
    ]
},

"MyBaseDto":{
    "type":"object",
    "properties":{
        "operator":{
            "type":"string"
        }
    },
    "discriminator":{
        "propertyName":"operator"
    }
},

"MyEqualsDto":{
    "type":"object",
    "allOf":[
        {
            "$ref":"#/components/schemas/MyBaseDto"
        },
        {
            "type":"object",
            "properties":{
                "field":{
                    "type":"string"
                },
                "value":{
                    "type":"string"
                }
            }
        }
    ]
},

"MyOrDto":{
    "type":"object",
    "allOf":[
        {
            "$ref":"#/components/schemas/MyBaseDto"
        }
    ]
}

For some reason, the MyAndDto generates correctly with the inherited parts property. But, the identical MyOrDto is missing the inherited parts property entirely.

If you switch the order of the @JsonSubTypes annotations:

@JsonSubTypes({ @JsonSubTypes.Type(value = MyOrDto.class, name = "or"),
        @JsonSubTypes.Type(value = MyAndDto.class, name = "and"),
        @JsonSubTypes.Type(value = MyEqualsDto.class, name = "equals") })

Then the MyOrDto generates correctly, and MyAndDto is incomplete.

I tried debugging and quickly got lost, but, to me it looked like the issue might be somewhere in io.swagger.v3.core.jackson.ModelResolver.resolveSubtypes() where it ends up with some recursion going on because MyAndDto and MyOrDto both contain an array of MyBaseDto. Seems like on one of the recursive passes, an incomplete Schema is getting used.

Thank you.

@Micky002
Copy link

I have the same problem but i can't solve it with reordering in the @JsonSubTypes annotation. I have done some reordering in the controller method so there is the method which use the base type first and methods using subtypes comes after that method. Then the generation is correct.

The problem was that a List<BaseType> property was included in a subtype although i belongs to the base type. Then all other subtypes and also the base type miss this property.

@raghuraman1
Copy link
Contributor

raghuraman1 commented Sep 27, 2021

Hi @frantuma, @webron and @HugoMario,

I think I have a fix for this over here -https://github.com/teq-niq/sample/tree/swagger-core-issue3312-better
I found multiple issues.

To solve these two issues I used the OpenApiCustomiser() and also extended the SchemaSerializer. Did this last bit by modifying io/swagger/v3/core/util/ObjectMapperFactory.java

I am pretty sure there can be better and more thorough ways to solve these small problems.

While on the subject I do believe it can be useful allowing io.swagger.v3.core.jackson.SchemaSerializer to be extendible in general. If there is any other way to achieve same extensibility pls advice.

I am also copying @bnasslahsen of springdoc project here.

Raghu

@Nikos410
Copy link

Hello,

we are facing the same issue. Is there any news on this? Is there anyone we can do to help?

(FYI @SimonErm @Digirik @GeroSchaarmann)

@raghuraman1
Copy link
Contributor

raghuraman1 commented Aug 12, 2022

Hello,

we are facing the same issue. Is there any news on this? Is there anyone we can do to help?

(FYI @SimonErm @Digirik @GeroSchaarmann)

Hi @Nikos410

Did you try the workaround I showed here- https://github.com/teq-niq/sample/tree/swagger-core-issue3312-better.
Does it work for you?

Raghu

@Nikos410
Copy link

Hey @raghuraman1, kind of. All properties are present now, but the allOf is missing now for all schemas. All properties are specified as properties of the child Dto directly.

@Nikos410
Copy link

Oh, I just noticed out issue is similar, but not quite the same. I've opened #4234 for out specific issue.

@raghuraman1
Copy link
Contributor

Hi @Nikos410
Its better than missing properties. I hope you are able to use it for stopgap.
I do think its a important bug needing proper solving.
R

Hey @raghuraman1, kind of. All properties are present now, but the allOf is missing now for all schemas. All properties are specified as properties of the child Dto directly.

@Nikos410
Copy link

Its better than missing properties

That is very true. It sadly does not help us however. We are using the openapi-generator project for client generation. If the allof reference is missing, the generator does not properly generate the models (The child classes are not children of the base class in the generated model).

Right now we are patching the generates json spec manually before passing it to the client generator.

@raghuraman1
Copy link
Contributor

raghuraman1 commented Aug 17, 2022

@Nikos410 I agree with you. I have seen this problem especially around polymorphism and inheritence in models when its generated as swagger definitions. I realised that hand editing the yaml or json is the best bet till its resolved. I keep advising people to be very careful about the yaml/json. What I do is have a generated json saved somewhere. Hand edit in a copy and do codegen on 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

No branches or pull requests

4 participants