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

[Codegen] Convert "any type" to oneOf model #6051

Prev Previous commit
Next Next commit
Support any type
  • Loading branch information
sebastien-rosset committed Apr 27, 2020
commit fcc47b84065094f90965c2acee98e1efc5803814
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,10 @@ public String toDefaultValueWithParam(String name, Schema schema) {
**/
@SuppressWarnings("static-method")
public String getSchemaType(Schema schema) {
if (schema == null) {
// This is indicative of a bug in codegen.
throw new RuntimeException("getSchemaType schema argument is null");
}
if (schema instanceof ComposedSchema) { // composed schema
ComposedSchema cs = (ComposedSchema) schema;
// Get the interfaces, i.e. the set of elements under 'allOf', 'anyOf' or 'oneOf'.
Expand Down Expand Up @@ -2012,7 +2016,7 @@ public String getTypeDeclaration(String name) {
}

/**
* Output the type declaration of the property
* Output the language-specific type declaration of the property.
*
* @param schema property schema
* @return a string presentation of the property type
Expand Down Expand Up @@ -2114,20 +2118,22 @@ public CodegenModel getAnyTypeModel(String name, Schema schema) {
if (!ModelUtils.isAnyTypeSchema(schema)) {
throw new RuntimeException("Schema '" + name + "' is not 'any type'");
}
ComposedSchema s = (ComposedSchema) new ComposedSchema()
ComposedSchema cs = (ComposedSchema) new ComposedSchema()
.addAnyOfItem(new ObjectSchema().type("null"))
.addAnyOfItem(new BooleanSchema())
.addAnyOfItem(new StringSchema())
.addAnyOfItem(new IntegerSchema())
.addAnyOfItem(new NumberSchema())
.addAnyOfItem(new ArraySchema())
.addAnyOfItem(new MapSchema())
.name(name);
// The map keys must be strings and the values can be anything.
cs.addAnyOfItem(new MapSchema().additionalProperties(cs));
// The array items can be anything.
cs.addAnyOfItem(new ArraySchema().items(cs));
if (schema != null) {
s.setTitle(schema.getTitle());
s.setDescription(schema.getDescription());
cs.setTitle(schema.getTitle());
cs.setDescription(schema.getDescription());
Copy link
Contributor Author

@sebastien-rosset sebastien-rosset Apr 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I thought I should create a single "AnyType" schema, but in reality there may be corner cases where constraints other than "type" have been specified:
title
pattern
required
enum
minimum
maximum
exclusiveMinimum
exclusiveMaximum
multipleOf
minLength
maxLength
minItems
maxItems
uniqueItems
minProperties
maxProperties

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But aren't those constraints specific to types? If you had minItems it would only apply to dict and array, right? My take is if they have any of those constraints then they should be fully explicit and list all types. We are just trying to cover this one super general yoy said it could be anything case. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way that constraint question is the headache of specific generators. I agree with you about adding this model/schema once and then using it multiple places if the writers used it multiple places.

Copy link
Contributor Author

@sebastien-rosset sebastien-rosset Apr 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But aren't those constraints specific to types? If you had minItems it would only apply to dict and array, right? My take is if they have any of those constraints then they should be fully explicit and list all types. We are just trying to cover this one super general yoy said it could be anything case. What do you think?

I am planning to handle these edge cases later. Right now just trying to make the simple case work, i.e. no OAS attribute whatsoever is defined in the OAS schema, it's really any type. Even this simple case is not so simple.

Also, the good news is most of these constraints are specific to a type. The only constraints that apply to all types are type, enum and const: https://tools.ietf.org/html/draft-handrews-json-schema-validation-02

}
return fromModel(name, s);
return fromModel(name, cs);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,18 @@ public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return "[]" + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, inner));
inner = ModelUtils.unaliasSchema(this.openAPI, inner);
if (inner == null) {
throw new RuntimeException("Failed to unalias schema " + p);
}
return "[]" + getTypeDeclaration(inner);
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
return getSchemaType(p) + "[string]" + getTypeDeclaration(ModelUtils.unaliasSchema(this.openAPI, inner));
inner = ModelUtils.unaliasSchema(this.openAPI, inner);
if (inner == null) {
throw new RuntimeException("Failed to unalias schema " + p);
}
return getSchemaType(p) + "[string]" + getTypeDeclaration(inner);
}
//return super.getTypeDeclaration(p);

Expand Down