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

Change external $ref in maven plugin autogenerated schemas to allow any subclass for an abstract class property #393

Closed
takanuva15 opened this issue Nov 4, 2023 · 2 comments

Comments

@takanuva15
Copy link
Contributor

takanuva15 commented Nov 4, 2023

Hi, in the ExternalRefPackageExample.java sample code, we are able to set up $refs to other schemas so that we don't duplicate schemas between connected models.

I am auto-generating schemas for a bunch of model classes in my code using the maven plugin, and I've bumped into the issue where one of my models is declaring a List<BaseClass> as an attribute but the auto-generated schema literally $refs to that BaseClass schema instead of its subclasses.

Here's a quick example:
Animal.java (BaseClass)

public abstract class Animal {
	protected String name;
	protected int numLegs;
}

Cat.java and Dog.java (SubClass)

public class Cat extends Animal {
	private int numWhiskers;
}

public class Dog extends Animal{
	private int barkVolume;
}

PetStore.java (Separate class with List<Animal>)

public class PetStore {
	private List<Animal> pets;
}

I set up the maven plugin and the ExternalRefPackageExample module (along with a yml objectmapper), and this is the schema that gets generated for PetStore.java:
PetStore-schema.yml

$schema: https://json-schema.org/draft/2020-12/schema
type: object
properties:
  pets:
    type: array
    items:
      $ref: classpath:///schemas/Animal-schema.yml
unevaluatedProperties: false

I need to use these schemas to verify my API responses, so I have intentionally added unevaluatedProperties: false to make sure there are no unexpected properties.

However, since the schema ref in PetStore-schema.yml is to Animal-schema.yml, if my API response returns an instance of Cat with the numWhiskers attribute, the schema validaton fails because Animal-schema.yml obviously wouldn't contain the numWhiskers property.

I think the appropriate way to fix this would be for the PetStore schema $ref to point to any of Animal's subclasses, eg something like this:

$schema: https://json-schema.org/draft/2020-12/schema
type: object
properties:
  pets:
    type: array
    items:
      anyOf:
        - $ref: classpath:///schemas/Cat-schema.yml
        - $ref: classpath:///schemas/Dog-schema.yml
unevaluatedProperties: false

Note: I saw the SubtypeLookUpExample.java that's in the examples, but it seems to change the Animal schema to include all subtype properties rather than allow any of the subtype schemas.

Assuming all the above makes sense, do you know how I could adjust the ExternalRefPackage module so that abstract class refs are resolved to anyOf their subclass refs, rather than just the base class?

(I have made an MVE repo that demonstrates the above issue with the schema generation. You can clone the repo and run mvn test-compile and the generated schemas under src/test/resources/schemas will match what I've discussed above.)

@takanuva15 takanuva15 changed the title Change external ref in maven plugin autogenerated schemas to allow any subclass for an abstract class property Change external $ref in maven plugin autogenerated schemas to allow any subclass for an abstract class property Nov 4, 2023
@CarstenWickner
Copy link
Member

HI @takanuva15,

I tried using the subtype resolver from the example you referenced, which resulted exactly in the anyOf being produced, as per your target schema here.

Not sure what went wrong for you before, which is why I created the corresponding pull request on your example repository: takanuva15/jsonschema-generator-ref-subclass-instead-of-baseclass#1

@takanuva15
Copy link
Contributor Author

Hmm looks like I hadn't set up the code correctly when I was trying it. Thanks for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants