From e863dbcf882032e4ea0a5549178f493530d4edfa Mon Sep 17 00:00:00 2001 From: Louisa Spicer Date: Tue, 9 Jan 2024 12:07:59 +0000 Subject: [PATCH] chore: update openapi jsonschema to group any messages with equals, notEquals and oneOf fields --- runtime/jsonschema/jsonschema.go | 14 ++++++-- runtime/jsonschema/jsonschema_test.go | 4 ++- runtime/jsonschema/testdata/list.json | 49 ++++++++++++++++++++------- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/runtime/jsonschema/jsonschema.go b/runtime/jsonschema/jsonschema.go index 44b2de307..84c933751 100644 --- a/runtime/jsonschema/jsonschema.go +++ b/runtime/jsonschema/jsonschema.go @@ -148,6 +148,16 @@ func JSONSchemaForActionResponse(ctx context.Context, schema *proto.Schema, acti } } +func contains(s []*proto.MessageField, e string) bool { + for _, input := range s { + if input.Name == e { + return true + } + } + + return false +} + // Generates JSONSchema for an operation by generating properties for the root input message. // Any subsequent nested messages are referenced. func JSONSchemaForMessage(ctx context.Context, schema *proto.Schema, action *proto.Action, message *proto.Message) JSONSchema { @@ -170,7 +180,8 @@ func JSONSchemaForMessage(ctx context.Context, schema *proto.Schema, action *pro if !isAny { // Certain messages should only allow one field to be set per request so we set these as a oneOf property - if message.Name == "IdQueryInput" || message.Name == "StringQueryInput" { + fieldsToGroup := (len(message.Fields) == 3 && contains(message.Fields, "equals") && contains(message.Fields, "notEquals") && contains(message.Fields, "oneOf")) + if message.Name == "StringQueryInput" || fieldsToGroup { oneOf := []JSONSchema{} for _, field := range message.Fields { @@ -202,7 +213,6 @@ func JSONSchemaForMessage(ctx context.Context, schema *proto.Schema, action *pro root.OneOf = oneOf root.Type = nil - } else { for _, field := range message.Fields { prop := jsonSchemaForField(ctx, schema, action, field.Type, field.Nullable) diff --git a/runtime/jsonschema/jsonschema_test.go b/runtime/jsonschema/jsonschema_test.go index bbda46047..2a819faf3 100644 --- a/runtime/jsonschema/jsonschema_test.go +++ b/runtime/jsonschema/jsonschema_test.go @@ -733,7 +733,7 @@ func TestValidateRequest(t *testing.T) { errors: map[string][]string{ "where.id": {`Must validate one and only one schema (oneOf)`, `Invalid type. Expected: object, given: null`}, "where.title": {`Must validate one and only one schema (oneOf)`, `Invalid type. Expected: object, given: null`}, - "where.genre": {`Invalid type. Expected: object, given: null`}, + "where.genre": {`Must validate one and only one schema (oneOf)`, `Invalid type. Expected: object, given: null`}, "where.price": {`Invalid type. Expected: object, given: null`}, "where.available": {`Invalid type. Expected: object, given: null`}, "where.createdAt": {`Invalid type. Expected: object, given: null`}, @@ -752,6 +752,7 @@ func TestValidateRequest(t *testing.T) { opName: "listBooks", request: `{"where": {"genre": {"equals": "Sci-fi"}}}`, errors: map[string][]string{ + "where.genre": {`Must validate one and only one schema (oneOf)`}, "where.genre.equals": {`where.genre.equals must be one of the following: "Romance", "Horror", null`}, }, }, @@ -760,6 +761,7 @@ func TestValidateRequest(t *testing.T) { opName: "listBooks", request: `{"where": {"genre": {"oneOf": ["Sci-fi"]}}}`, errors: map[string][]string{ + "where.genre": {`Must validate one and only one schema (oneOf)`}, "where.genre.oneOf.0": {`where.genre.oneOf.0 must be one of the following: "Romance", "Horror"`}, }, }, diff --git a/runtime/jsonschema/testdata/list.json b/runtime/jsonschema/testdata/list.json index 81c936f31..5a4c8ebac 100644 --- a/runtime/jsonschema/testdata/list.json +++ b/runtime/jsonschema/testdata/list.json @@ -64,22 +64,45 @@ "additionalProperties": false }, "HobbyQueryInput": { - "type": "object", - "properties": { - "equals": { - "enum": ["Tennis", "Chess", null] + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "equals": { + "enum": ["Tennis", "Chess", null] + } + }, + "required": ["equals"], + "title": "equals", + "type": "object" }, - "notEquals": { - "enum": ["Tennis", "Chess", null] + { + "additionalProperties": false, + "properties": { + "notEquals": { + "enum": ["Tennis", "Chess", null] + } + }, + "required": ["notEquals"], + "title": "notEquals", + "type": "object" }, - "oneOf": { - "type": "array", - "items": { - "enum": ["Tennis", "Chess"] - } + { + "additionalProperties": false, + "properties": { + "oneOf": { + "items": { + "enum": ["Tennis", "Chess"] + }, + "type": "array" + } + }, + "required": ["oneOf"], + "title": "oneOf", + "type": "object" } - }, - "additionalProperties": false + ], + "unevaluatedProperties": false }, "IdQueryInput": { "unevaluatedProperties": false,