swagger-core icon indicating copy to clipboard operation
swagger-core copied to clipboard

JSONObject schema being referenced instead of example being populated

Open Axiloom opened this issue 3 years ago • 2 comments

Not entirely sure if this is a feature or a bug or even if there is a way to fix it.

I have the following schema annotation in code that has org.json.simple JSONObject type:

@Schema(
    description = "userCredentials",
    example = "{\"id\": 1012}"
)
private JSONObject userCredentials;

In the openapi.yaml thats generated, I get:

        ...
        userCredentials:
          $ref: '#/components/schemas/JSONObject'
        ...

What I was expecting was something like this:

        ...
        userCredentials:
          description: userCredentials
          example:
            id: 1012
        ...

There are a bunch of other areas in the codebase that use JSONObject type (some with schema annotations and some without), and some of those schemas do display correctly for JSONObject, however there are a few that just use a reference to the JSONObject schema.

So my questions are:

  1. Why is a JSONObject schema even being created in the first place?
  2. Is there a way I can prevent swagger-core from generating a schema for JSONObject (or any particular type)?
  3. Is there a way I can force particular variables to use the local schema info instead of a reference to JSONObject?

Axiloom avatar May 12 '22 22:05 Axiloom

I found a solution with the following converter:

private static class DuplicateTypeConverter implements ModelConverter {

        private final Class<?> clazz;

        public DuplicateTypeConverter(Class<?> clazz) {
            this.clazz = clazz;
        }

        @Override
        public Schema<?> resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {

            if (type.isSchemaProperty()) {

                JavaType _type = Json.mapper().constructType(type.getType());

                if (_type != null) {

                    if (clazz.equals(_type.getRawClass())) {
                        if (context.getDefinedModels().containsKey(clazz.getSimpleName())) {
                            type.setResolveAsRef(false);
                        }
                    }
                }
            }
            if (chain.hasNext()) {
                return chain.next().resolve(type, context, chain);
            } else {
                return null;
            }
        }
    }

I still think this is an issue with swagger-core. I would think in ModelResolver.java, lines 869-871:

if (context.getDefinedModels().containsKey(model.getName())) {
    model = new Schema().$ref(constructRef(model.getName()));
}

it should instead be:

if (context.getDefinedModels().containsKey(model.getName()) && context.getDefinedModels().get(model.getName()).equals(model)) {
    model = new Schema().$ref(constructRef(model.getName()));
}

So basically if the metadata of the models differ, we should not use a reference, but instead return the schema. The only concern I have with submitting this is that I don't know if it goes against the specification

Axiloom avatar May 19 '22 15:05 Axiloom

An alternate solution would be to include setResolveAsRef in the Schema type, so we can force specific models to not use a reference, but once again this is really just a bandaid over the issue at hand.

Axiloom avatar May 19 '22 15:05 Axiloom