From 3469322725c0968fb49b3552ff59ead8bb9d735a Mon Sep 17 00:00:00 2001 From: Prawn Date: Thu, 30 Sep 2021 10:46:25 +1300 Subject: [PATCH] Fixing $ref behaviour (#82) * Coming closer * Conversion looking good now * Reverting Makefile * Regenerated sample schemas (a lot of changes here) * Reverting tests * Bumping deps * Rebased * Regenerating test data * Keeping root references * Ordering tests * Slowly going through the tests * resetting test schemas * Using more explicid references * Tests * README update * Removing refPrefix cruft (this will be another PR) * Updating tests for fieldoptions * Reinstating ref prefix and an ID for the root type * Regenerated jsonschemas * Updating tests for definitions references * Simplifying nestedMessage logic * Schema version only in the root object * Regenerating samples * Completely removing the IDs Co-authored-by: Chrusty <> --- README.md | 29 ++ go.mod | 7 +- go.sum | 13 +- internal/converter/converter.go | 5 +- internal/converter/converter_test.go | 375 +++++++++++------- internal/converter/testdata/array_of_enums.go | 59 ++- .../converter/testdata/array_of_messages.go | 125 +++--- .../converter/testdata/array_of_objects.go | 225 ++++++----- .../converter/testdata/array_of_primitives.go | 340 ++++++++-------- internal/converter/testdata/bytes_payload.go | 29 +- .../converter/testdata/cyclical_reference.go | 250 ++++++------ internal/converter/testdata/enum_ception.go | 132 +++--- internal/converter/testdata/enum_imported.go | 53 ++- .../testdata/enum_nested_reference.go | 61 +-- .../converter/testdata/enum_with_message.go | 49 ++- internal/converter/testdata/field_options.go | 33 +- internal/converter/testdata/first_enum.go | 4 + internal/converter/testdata/first_message.go | 45 ++- internal/converter/testdata/google_value.go | 53 ++- internal/converter/testdata/hidden_fields.go | 27 +- internal/converter/testdata/imported_enum.go | 4 + internal/converter/testdata/json_fields.go | 54 +-- internal/converter/testdata/maps.go | 135 ++++--- .../converter/testdata/message_kind_10.go | 44 +- .../converter/testdata/message_kind_11.go | 84 ++-- .../converter/testdata/message_kind_12.go | 236 ++++++----- .../testdata/message_with_comments.go | 23 +- internal/converter/testdata/nested_message.go | 37 +- internal/converter/testdata/nested_object.go | 33 +- internal/converter/testdata/oneof.go | 69 ++-- .../converter/testdata/payload_message.go | 85 ++-- .../converter/testdata/payload_message_2.go | 107 ++--- .../testdata/proto2_nested_message.go | 47 ++- .../testdata/proto2_nested_object.go | 53 ++- .../testdata/proto2_payload_message.go | 97 +++-- .../converter/testdata/proto2_required.go | 44 +- .../converter/testdata/proto3_required.go | 46 ++- internal/converter/testdata/second_enum.go | 4 + internal/converter/testdata/second_message.go | 45 ++- internal/converter/testdata/self_reference.go | 30 +- internal/converter/testdata/timestamp.go | 23 +- internal/converter/testdata/wellknown.go | 71 ++-- internal/converter/types.go | 83 ++-- internal/protos/options.pb.go | 35 +- jsonschemas/ArrayOfEnums.jsonschema | 45 ++- jsonschemas/ArrayOfMessages.jsonschema | 215 +++++----- jsonschemas/ArrayOfObjects.jsonschema | 215 +++++----- jsonschemas/ArrayOfPrimitives.jsonschema | 157 ++++---- jsonschemas/Enumception.jsonschema | 128 +++--- jsonschemas/FirstMessage.jsonschema | 41 +- jsonschemas/GoogleValue.jsonschema | 49 ++- jsonschemas/HiddenFields.jsonschema | 23 +- jsonschemas/JSONFields.jsonschema | 47 ++- jsonschemas/Maps.jsonschema | 119 +++--- jsonschemas/MessageKind10.jsonschema | 41 +- jsonschemas/MessageKind11.jsonschema | 81 ++-- jsonschemas/MessageKind12.jsonschema | 233 ++++++----- jsonschemas/MessageWithComments.jsonschema | 21 +- jsonschemas/NestedMessage.jsonschema | 25 +- jsonschemas/NestedObject.jsonschema | 25 +- jsonschemas/OneOf.jsonschema | 55 ++- jsonschemas/PayloadMessage.jsonschema | 81 ++-- jsonschemas/PayloadMessage2.jsonschema | 95 ++--- jsonschemas/Proto2NestedMessage.jsonschema | 33 +- jsonschemas/Proto2NestedObject.jsonschema | 35 +- jsonschemas/Proto2PayloadMessage.jsonschema | 87 ++-- jsonschemas/Proto2Required.jsonschema | 35 +- jsonschemas/Proto3Required.jsonschema | 37 +- jsonschemas/SecondMessage.jsonschema | 41 +- jsonschemas/Timestamp.jsonschema | 19 +- jsonschemas/WellKnown.jsonschema | 67 ++-- 71 files changed, 3142 insertions(+), 2311 deletions(-) diff --git a/README.md b/README.md index 19151f17..d66420b4 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,35 @@ Useful for people who define their data using ProtoBuf, but use JSON for the "wi "Heavily influenced" by [Google's protobuf-to-BigQuery-schema compiler](https://github.com/GoogleCloudPlatform/protoc-gen-bq-schema). + +## Generated Schemas + +- One JSONSchema file is generated for each root-level proto message and ENUM. These are intended to be stand alone self-contained schemas which can be used to validate a payload derived from their source proto message +- Nested message schemas become [referenced "definitions"](https://cswr.github.io/JsonSchema/spec/definitions_references/). This means that you know the name of the proto message they came from, and their schema is not duplicated (within the context of one JSONSchema file at least) + + +## Logic + +- For each proto file provided + - Generates schema for each ENUM + - JSONSchema filename deried from ENUM name + - Generates schema for each Message + - Builds a list of every nested message and converts them to JSONSchema + - Recursively converts attributes and nested messages within the root message + - Optionally makes all fields required + - Optionally allows NULL values + - Optionally allows additional properties + - Optionally marks all fields required + - Specially marked fields are labelled required (options.proto) + - Specially marked fields are omitted (options.proto) + - Special handling for "OneOf" + - Special handling for arrays + - Special handling for maps + - Injects references to nested messages + - JSONSchema filename derived from Message name + - Bundles these into a protoc generator response + + ## Installation > Note: This tool requires Go 1.11+ to be installed. diff --git a/go.mod b/go.mod index f0b47ce6..d69fd4eb 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,15 @@ module github.com/chrusty/protoc-gen-jsonschema go 1.14 require ( - github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9 + github.com/alecthomas/jsonschema v0.0.0-20210918223802-a1d3f4b43d7b github.com/golang/protobuf v1.5.0 - github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 + github.com/iancoleman/orderedmap v0.2.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/kr/pretty v0.1.0 // indirect github.com/sirupsen/logrus v1.4.2 github.com/stretchr/testify v1.4.0 github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.1.0 + github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 // indirect google.golang.org/protobuf v1.27.1 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect diff --git a/go.sum b/go.sum index ca591b51..53938c5b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9 h1:h+KAZEUnNceFhqyH46BgwH4lk8m6pdR/3x3h7IPn7VA= -github.com/alecthomas/jsonschema v0.0.0-20200217214135-7152f22193c9/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= +github.com/alecthomas/jsonschema v0.0.0-20210918223802-a1d3f4b43d7b h1:SM/PhkjhbeX1w/Jkv7dHFYDn2y4/88XZp3CIqVHsdcs= +github.com/alecthomas/jsonschema v0.0.0-20210918223802-a1d3f4b43d7b/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,8 +7,9 @@ github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -24,15 +25,17 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= -github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 3c04eeae..c777b329 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -17,6 +17,7 @@ import ( ) const ( + defaultRefPrefix = "#/definitions/" messageDelimiter = "+" ) @@ -25,6 +26,7 @@ type Converter struct { Flags ConverterFlags ignoredFieldOption string logger *logrus.Logger + refPrefix string requiredFieldOption string sourceInfo *sourceCodeInfo messageTargets []string @@ -45,7 +47,8 @@ type ConverterFlags struct { // New returns a configured *Converter: func New(logger *logrus.Logger) *Converter { return &Converter{ - logger: logger, + logger: logger, + refPrefix: defaultRefPrefix, } } diff --git a/internal/converter/converter_test.go b/internal/converter/converter_test.go index 314c6e0c..0492ae7f 100644 --- a/internal/converter/converter_test.go +++ b/internal/converter/converter_test.go @@ -13,6 +13,7 @@ import ( plugin "github.com/golang/protobuf/protoc-gen-go/plugin" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + "github.com/xeipuuv/gojsonschema" "github.com/chrusty/protoc-gen-jsonschema/internal/converter/testdata" ) @@ -22,11 +23,13 @@ const ( ) type sampleProto struct { - Flags ConverterFlags - ExpectedJSONSchema []string - FilesToGenerate []string - ProtoFileName string - TargetedMessages []string + Flags ConverterFlags + ExpectedJSONSchema []string + FilesToGenerate []string + ObjectsToValidateFail []string + ObjectsToValidatePass []string + ProtoFileName string + TargetedMessages []string } func TestGenerateJsonSchema(t *testing.T) { @@ -77,7 +80,23 @@ func testConvertSampleProto(t *testing.T, sampleProto sampleProto) { t.Fail() } else { for responseFileIndex, responseFile := range response.File { + + // Ensure that the generated schema matches the expected (canned) one: assert.Equal(t, strings.TrimSpace(sampleProto.ExpectedJSONSchema[responseFileIndex]), *responseFile.Content, "Incorrect JSON-Schema returned for sample proto file (%v)", sampleProtoFileName) + + // Validate any intended-to-fail data against the new schema: + if len(sampleProto.ObjectsToValidateFail) >= responseFileIndex+1 { + valid, err := validateSchema(*responseFile.Content, sampleProto.ObjectsToValidateFail[responseFileIndex]) + assert.NoError(t, err) + assert.False(t, valid, "Expected canned data to fail validation)") + } + + // Validate any intended-to-pass data against the new schema: + if len(sampleProto.ObjectsToValidatePass) >= responseFileIndex+1 { + valid, err := validateSchema(*responseFile.Content, sampleProto.ObjectsToValidatePass[responseFileIndex]) + assert.NoError(t, err, "Error validating canned data with generated schema") + assert.True(t, valid, "Expected canned data validate)") + } } } @@ -96,154 +115,227 @@ func testConvertSampleProto(t *testing.T, sampleProto sampleProto) { func configureSampleProtos() map[string]sampleProto { return map[string]sampleProto{ + "AllRequired": { + Flags: ConverterFlags{AllFieldsRequired: true}, + ExpectedJSONSchema: []string{testdata.PayloadMessage2}, + FilesToGenerate: []string{"PayloadMessage2.proto"}, + ProtoFileName: "PayloadMessage2.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessage2Fail}, + ObjectsToValidatePass: []string{testdata.PayloadMessage2Pass}, + }, + "ArrayOfEnums": { + ExpectedJSONSchema: []string{testdata.ArrayOfEnums}, + FilesToGenerate: []string{"ArrayOfEnums.proto"}, + ProtoFileName: "ArrayOfEnums.proto", + ObjectsToValidateFail: []string{testdata.ArrayOfEnumsFail}, + ObjectsToValidatePass: []string{testdata.ArrayOfEnumsPass}, + }, "ArrayOfMessages": { - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ArrayOfMessages}, - FilesToGenerate: []string{"ArrayOfMessages.proto", "PayloadMessage.proto"}, - ProtoFileName: "ArrayOfMessages.proto", + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ArrayOfMessages}, + FilesToGenerate: []string{"ArrayOfMessages.proto", "PayloadMessage.proto"}, + ProtoFileName: "ArrayOfMessages.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessageFail, testdata.ArrayOfMessagesFail}, + ObjectsToValidatePass: []string{testdata.PayloadMessagePass, testdata.ArrayOfMessagesPass}, }, "ArrayOfObjects": { - Flags: ConverterFlags{AllowNullValues: true}, - ExpectedJSONSchema: []string{testdata.ArrayOfObjects}, - FilesToGenerate: []string{"ArrayOfObjects.proto"}, - ProtoFileName: "ArrayOfObjects.proto", + Flags: ConverterFlags{AllowNullValues: true}, + ExpectedJSONSchema: []string{testdata.ArrayOfObjects}, + FilesToGenerate: []string{"ArrayOfObjects.proto"}, + ProtoFileName: "ArrayOfObjects.proto", + ObjectsToValidateFail: []string{testdata.ArrayOfObjectsFail}, + ObjectsToValidatePass: []string{testdata.ArrayOfObjectsPass}, }, "ArrayOfPrimitives": { - Flags: ConverterFlags{AllowNullValues: true}, - ExpectedJSONSchema: []string{testdata.ArrayOfPrimitives}, - FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, - ProtoFileName: "ArrayOfPrimitives.proto", - }, - "BytesPayload": { - ExpectedJSONSchema: []string{testdata.BytesPayload}, - FilesToGenerate: []string{"BytesPayload.proto"}, - ProtoFileName: "BytesPayload.proto", + Flags: ConverterFlags{AllowNullValues: true}, + ExpectedJSONSchema: []string{testdata.ArrayOfPrimitives}, + FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, + ProtoFileName: "ArrayOfPrimitives.proto", + ObjectsToValidateFail: []string{testdata.ArrayOfPrimitivesFail}, + ObjectsToValidatePass: []string{testdata.ArrayOfPrimitivesPass}, }, "ArrayOfPrimitivesDouble": { Flags: ConverterFlags{ AllowNullValues: true, UseProtoAndJSONFieldNames: true, }, - ExpectedJSONSchema: []string{testdata.ArrayOfPrimitivesDouble}, - FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, - ProtoFileName: "ArrayOfPrimitives.proto", + ExpectedJSONSchema: []string{testdata.ArrayOfPrimitivesDouble}, + FilesToGenerate: []string{"ArrayOfPrimitives.proto"}, + ProtoFileName: "ArrayOfPrimitives.proto", + ObjectsToValidateFail: []string{testdata.ArrayOfPrimitivesDoubleFail}, + ObjectsToValidatePass: []string{testdata.ArrayOfPrimitivesDoublePass}, + }, + "BytesPayload": { + ExpectedJSONSchema: []string{testdata.BytesPayload}, + FilesToGenerate: []string{"BytesPayload.proto"}, + ProtoFileName: "BytesPayload.proto", + ObjectsToValidateFail: []string{testdata.BytesPayloadFail}, + }, + "Comments": { + ExpectedJSONSchema: []string{testdata.MessageWithComments}, + FilesToGenerate: []string{"MessageWithComments.proto"}, + ProtoFileName: "MessageWithComments.proto", + ObjectsToValidateFail: []string{testdata.MessageWithCommentsFail}, + }, + "CyclicalReference": { + ExpectedJSONSchema: []string{testdata.CyclicalReferenceMessageM, testdata.CyclicalReferenceMessageFoo, testdata.CyclicalReferenceMessageBar, testdata.CyclicalReferenceMessageBaz}, + FilesToGenerate: []string{"CyclicalReference.proto"}, + ProtoFileName: "CyclicalReference.proto", }, "EnumNestedReference": { - ExpectedJSONSchema: []string{testdata.EnumNestedReference}, - FilesToGenerate: []string{"EnumNestedReference.proto"}, - ProtoFileName: "EnumNestedReference.proto", + ExpectedJSONSchema: []string{testdata.EnumNestedReference}, + FilesToGenerate: []string{"EnumNestedReference.proto"}, + ProtoFileName: "EnumNestedReference.proto", + ObjectsToValidateFail: []string{testdata.EnumNestedReferenceFail}, + ObjectsToValidatePass: []string{testdata.EnumNestedReferencePass}, }, "EnumWithMessage": { - ExpectedJSONSchema: []string{testdata.EnumWithMessage}, - FilesToGenerate: []string{"EnumWithMessage.proto"}, - ProtoFileName: "EnumWithMessage.proto", + ExpectedJSONSchema: []string{testdata.EnumWithMessage}, + FilesToGenerate: []string{"EnumWithMessage.proto"}, + ProtoFileName: "EnumWithMessage.proto", + ObjectsToValidateFail: []string{testdata.EnumWithMessageFail}, + ObjectsToValidatePass: []string{testdata.EnumWithMessagePass}, }, "EnumImport": { - ExpectedJSONSchema: []string{testdata.EnumImport}, - FilesToGenerate: []string{"ImportEnum.proto"}, - ProtoFileName: "ImportEnum.proto", + ExpectedJSONSchema: []string{testdata.EnumImport}, + FilesToGenerate: []string{"ImportEnum.proto"}, + ProtoFileName: "ImportEnum.proto", + ObjectsToValidateFail: []string{testdata.EnumImportFail}, + ObjectsToValidatePass: []string{testdata.EnumImportPass}, }, "EnumCeption": { - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ImportedEnum, testdata.EnumCeption}, - FilesToGenerate: []string{"Enumception.proto", "PayloadMessage.proto", "ImportedEnum.proto"}, - ProtoFileName: "Enumception.proto", - }, - "ImportedEnum": { - ExpectedJSONSchema: []string{testdata.ImportedEnum}, - FilesToGenerate: []string{"ImportedEnum.proto"}, - ProtoFileName: "ImportedEnum.proto", + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.ImportedEnum, testdata.EnumCeption}, + FilesToGenerate: []string{"Enumception.proto", "PayloadMessage.proto", "ImportedEnum.proto"}, + ProtoFileName: "Enumception.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessageFail, testdata.ImportedEnumFail, testdata.EnumCeptionFail}, + ObjectsToValidatePass: []string{testdata.PayloadMessagePass, testdata.ImportedEnumPass, testdata.EnumCeptionPass}, }, - "NestedMessage": { - ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.NestedMessage}, - FilesToGenerate: []string{"NestedMessage.proto", "PayloadMessage.proto"}, - ProtoFileName: "NestedMessage.proto", - }, - "NestedObject": { - ExpectedJSONSchema: []string{testdata.NestedObject}, - FilesToGenerate: []string{"NestedObject.proto"}, - ProtoFileName: "NestedObject.proto", - }, - "PayloadMessage": { - ExpectedJSONSchema: []string{testdata.PayloadMessage}, - FilesToGenerate: []string{"PayloadMessage.proto"}, - ProtoFileName: "PayloadMessage.proto", + "GoogleValue": { + ExpectedJSONSchema: []string{testdata.GoogleValue}, + FilesToGenerate: []string{"GoogleValue.proto"}, + ProtoFileName: "GoogleValue.proto", + ObjectsToValidateFail: []string{testdata.GoogleValueFail}, + ObjectsToValidatePass: []string{testdata.GoogleValuePass}, }, - "SeveralEnums": { - ExpectedJSONSchema: []string{testdata.FirstEnum, testdata.SecondEnum}, - FilesToGenerate: []string{"SeveralEnums.proto"}, - ProtoFileName: "SeveralEnums.proto", + "HiddenFields": { + ExpectedJSONSchema: []string{testdata.FieldOptions, testdata.HiddenFields}, + FilesToGenerate: []string{"options.proto", "HiddenFields.proto"}, + ProtoFileName: "HiddenFields.proto", + ObjectsToValidateFail: []string{testdata.FieldOptionsFail, testdata.HiddenFieldsFail}, + ObjectsToValidatePass: []string{testdata.FieldOptionsPass, testdata.HiddenFieldsPass}, }, - "SeveralMessages": { - ExpectedJSONSchema: []string{testdata.FirstMessage, testdata.SecondMessage}, - FilesToGenerate: []string{"SeveralMessages.proto"}, - ProtoFileName: "SeveralMessages.proto", + "ImportedEnum": { + ExpectedJSONSchema: []string{testdata.ImportedEnum}, + FilesToGenerate: []string{"ImportedEnum.proto"}, + ProtoFileName: "ImportedEnum.proto", + ObjectsToValidateFail: []string{testdata.ImportedEnumFail}, + ObjectsToValidatePass: []string{testdata.ImportedEnumPass}, }, - "ArrayOfEnums": { - ExpectedJSONSchema: []string{testdata.ArrayOfEnums}, - FilesToGenerate: []string{"ArrayOfEnums.proto"}, - ProtoFileName: "ArrayOfEnums.proto", + "JSONFields": { + Flags: ConverterFlags{UseJSONFieldnamesOnly: true}, + ExpectedJSONSchema: []string{testdata.JSONFields}, + FilesToGenerate: []string{"JSONFields.proto"}, + ProtoFileName: "JSONFields.proto", + ObjectsToValidateFail: []string{testdata.JSONFieldsFail}, + ObjectsToValidatePass: []string{testdata.JSONFieldsPass}, }, "Maps": { - ExpectedJSONSchema: []string{testdata.Maps}, - FilesToGenerate: []string{"Maps.proto"}, - ProtoFileName: "Maps.proto", - }, - "Comments": { - ExpectedJSONSchema: []string{testdata.MessageWithComments}, - FilesToGenerate: []string{"MessageWithComments.proto"}, - ProtoFileName: "MessageWithComments.proto", - }, - "SelfReference": { - ExpectedJSONSchema: []string{testdata.SelfReference}, - FilesToGenerate: []string{"SelfReference.proto"}, - ProtoFileName: "SelfReference.proto", - }, - "CyclicalReference": { - ExpectedJSONSchema: []string{testdata.CyclicalReferenceMessageM, testdata.CyclicalReferenceMessageFoo, testdata.CyclicalReferenceMessageBar, testdata.CyclicalReferenceMessageBaz}, - FilesToGenerate: []string{"CyclicalReference.proto"}, - ProtoFileName: "CyclicalReference.proto", + ExpectedJSONSchema: []string{testdata.Maps}, + FilesToGenerate: []string{"Maps.proto"}, + ProtoFileName: "Maps.proto", + ObjectsToValidateFail: []string{testdata.MapsFail}, + ObjectsToValidatePass: []string{testdata.MapsPass}, }, - "WellKnown": { - ExpectedJSONSchema: []string{testdata.WellKnown}, - FilesToGenerate: []string{"WellKnown.proto"}, - ProtoFileName: "WellKnown.proto", + "NestedMessage": { + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.NestedMessage}, + FilesToGenerate: []string{"NestedMessage.proto", "PayloadMessage.proto"}, + ProtoFileName: "NestedMessage.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessageFail, testdata.NestedMessageFail}, + ObjectsToValidatePass: []string{testdata.PayloadMessagePass, testdata.NestedMessagePass}, }, - "Timestamp": { - ExpectedJSONSchema: []string{testdata.Timestamp}, - FilesToGenerate: []string{"Timestamp.proto"}, - ProtoFileName: "Timestamp.proto", + "NestedObject": { + ExpectedJSONSchema: []string{testdata.NestedObject}, + FilesToGenerate: []string{"NestedObject.proto"}, + ProtoFileName: "NestedObject.proto", + ObjectsToValidateFail: []string{testdata.NestedObjectFail}, + ObjectsToValidatePass: []string{testdata.NestedObjectPass}, }, "NoPackage": { ExpectedJSONSchema: []string{}, FilesToGenerate: []string{}, ProtoFileName: "NoPackage.proto", }, - "PackagePrefix": { - Flags: ConverterFlags{PrefixSchemaFilesWithPackage: true}, - ExpectedJSONSchema: []string{testdata.Timestamp}, - FilesToGenerate: []string{"Timestamp.proto"}, - ProtoFileName: "Timestamp.proto", + "OneOf": { + Flags: ConverterFlags{AllFieldsRequired: true, EnforceOneOf: true}, + ExpectedJSONSchema: []string{testdata.OneOf}, + FilesToGenerate: []string{"OneOf.proto"}, + ProtoFileName: "OneOf.proto", + ObjectsToValidateFail: []string{testdata.OneOfFail}, + ObjectsToValidatePass: []string{testdata.OneOfPass}, }, - "Proto2Required": { - ExpectedJSONSchema: []string{testdata.Proto2Required}, - FilesToGenerate: []string{"Proto2Required.proto"}, - ProtoFileName: "Proto2Required.proto", + "PackagePrefix": { + Flags: ConverterFlags{PrefixSchemaFilesWithPackage: true}, + ExpectedJSONSchema: []string{testdata.Timestamp}, + FilesToGenerate: []string{"Timestamp.proto"}, + ProtoFileName: "Timestamp.proto", + ObjectsToValidateFail: []string{testdata.TimestampFail}, + ObjectsToValidatePass: []string{testdata.TimestampPass}, }, - "AllRequired": { - Flags: ConverterFlags{AllFieldsRequired: true}, - ExpectedJSONSchema: []string{testdata.PayloadMessage2}, - FilesToGenerate: []string{"PayloadMessage2.proto"}, - ProtoFileName: "PayloadMessage2.proto", + "PayloadMessage": { + ExpectedJSONSchema: []string{testdata.PayloadMessage}, + FilesToGenerate: []string{"PayloadMessage.proto"}, + ProtoFileName: "PayloadMessage.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessageFail}, + ObjectsToValidatePass: []string{testdata.PayloadMessagePass}, }, "Proto2NestedMessage": { - ExpectedJSONSchema: []string{testdata.Proto2PayloadMessage, testdata.Proto2NestedMessage}, - FilesToGenerate: []string{"Proto2PayloadMessage.proto", "Proto2NestedMessage.proto"}, - ProtoFileName: "Proto2NestedMessage.proto", + ExpectedJSONSchema: []string{testdata.Proto2PayloadMessage, testdata.Proto2NestedMessage}, + FilesToGenerate: []string{"Proto2PayloadMessage.proto", "Proto2NestedMessage.proto"}, + ProtoFileName: "Proto2NestedMessage.proto", + ObjectsToValidateFail: []string{testdata.Proto2PayloadMessageFail, testdata.Proto2NestedMessageFail}, + ObjectsToValidatePass: []string{testdata.Proto2PayloadMessagePass, testdata.Proto2NestedMessagePass}, }, "Proto2NestedObject": { - Flags: ConverterFlags{AllFieldsRequired: true}, - ExpectedJSONSchema: []string{testdata.Proto2NestedObject}, - FilesToGenerate: []string{"Proto2NestedObject.proto"}, - ProtoFileName: "Proto2NestedObject.proto", + Flags: ConverterFlags{AllFieldsRequired: true}, + ExpectedJSONSchema: []string{testdata.Proto2NestedObject}, + FilesToGenerate: []string{"Proto2NestedObject.proto"}, + ProtoFileName: "Proto2NestedObject.proto", + ObjectsToValidateFail: []string{testdata.Proto2NestedObjectFail}, + ObjectsToValidatePass: []string{testdata.Proto2NestedObjectPass}, + }, + "Proto2Required": { + ExpectedJSONSchema: []string{testdata.Proto2Required}, + FilesToGenerate: []string{"Proto2Required.proto"}, + ProtoFileName: "Proto2Required.proto", + ObjectsToValidateFail: []string{testdata.Proto2RequiredFail}, + ObjectsToValidatePass: []string{testdata.Proto2RequiredPass}, + }, + "Proto3Required": { + ExpectedJSONSchema: []string{testdata.FieldOptions, testdata.Proto3Required}, + FilesToGenerate: []string{"options.proto", "Proto3Required.proto"}, + ProtoFileName: "Proto3Required.proto", + ObjectsToValidateFail: []string{testdata.FieldOptionsFail, testdata.Proto3RequiredFail}, + ObjectsToValidatePass: []string{testdata.FieldOptionsPass, testdata.Proto3RequiredPass}, + }, + "SelfReference": { + ExpectedJSONSchema: []string{testdata.SelfReference}, + FilesToGenerate: []string{"SelfReference.proto"}, + ProtoFileName: "SelfReference.proto", + ObjectsToValidateFail: []string{testdata.SelfReferenceFail}, + ObjectsToValidatePass: []string{testdata.SelfReferencePass}, + }, + "SeveralEnums": { + ExpectedJSONSchema: []string{testdata.FirstEnum, testdata.SecondEnum}, + FilesToGenerate: []string{"SeveralEnums.proto"}, + ProtoFileName: "SeveralEnums.proto", + ObjectsToValidateFail: []string{testdata.FirstEnumFail, testdata.SecondEnumFail}, + ObjectsToValidatePass: []string{testdata.FirstEnumPass, testdata.SecondEnumPass}, + }, + "SeveralMessages": { + ExpectedJSONSchema: []string{testdata.FirstMessage, testdata.SecondMessage}, + FilesToGenerate: []string{"SeveralMessages.proto"}, + ProtoFileName: "SeveralMessages.proto", + ObjectsToValidateFail: []string{testdata.FirstMessageFail, testdata.SecondMessageFail}, + ObjectsToValidatePass: []string{testdata.FirstMessagePass, testdata.SecondMessagePass}, }, "TargetedMessages": { TargetedMessages: []string{"MessageKind10", "MessageKind11", "MessageKind12"}, @@ -251,32 +343,19 @@ func configureSampleProtos() map[string]sampleProto { FilesToGenerate: []string{"TwelveMessages.proto"}, ProtoFileName: "TwelveMessages.proto", }, - "GoogleValue": { - ExpectedJSONSchema: []string{testdata.GoogleValue}, - FilesToGenerate: []string{"GoogleValue.proto"}, - ProtoFileName: "GoogleValue.proto", - }, - "JSONFields": { - Flags: ConverterFlags{UseJSONFieldnamesOnly: true}, - ExpectedJSONSchema: []string{testdata.JSONFields}, - FilesToGenerate: []string{"JSONFields.proto"}, - ProtoFileName: "JSONFields.proto", - }, - "OneOf": { - Flags: ConverterFlags{AllFieldsRequired: true, EnforceOneOf: true}, - ExpectedJSONSchema: []string{testdata.OneOf}, - FilesToGenerate: []string{"OneOf.proto"}, - ProtoFileName: "OneOf.proto", - }, - "HiddenFields": { - ExpectedJSONSchema: []string{testdata.FieldOptions, testdata.HiddenFields}, - FilesToGenerate: []string{"options.proto", "HiddenFields.proto"}, - ProtoFileName: "HiddenFields.proto", + "Timestamp": { + ExpectedJSONSchema: []string{testdata.Timestamp}, + FilesToGenerate: []string{"Timestamp.proto"}, + ProtoFileName: "Timestamp.proto", + ObjectsToValidateFail: []string{testdata.TimestampFail}, + ObjectsToValidatePass: []string{testdata.TimestampPass}, }, - "Proto3Required": { - ExpectedJSONSchema: []string{testdata.FieldOptions, testdata.Proto3Required}, - FilesToGenerate: []string{"options.proto", "Proto3Required.proto"}, - ProtoFileName: "Proto3Required.proto", + "WellKnown": { + ExpectedJSONSchema: []string{testdata.WellKnown}, + FilesToGenerate: []string{"WellKnown.proto"}, + ProtoFileName: "WellKnown.proto", + ObjectsToValidateFail: []string{testdata.WellKnownFail}, + ObjectsToValidatePass: []string{testdata.WellKnownPass}, }, } } @@ -314,3 +393,21 @@ func mustReadProtoFiles(t *testing.T, includePath string, filenames ...string) * } return fds } + +func validateSchema(jsonSchema, jsonData string) (bool, error) { + var valid = false + + // Load the JSON schema: + schemaLoader := gojsonschema.NewStringLoader(jsonSchema) + + // Load the JSON document we'll be validating: + documentLoader := gojsonschema.NewStringLoader(jsonData) + + // Validate: + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil || result == nil { + return valid, err + } + + return result.Valid(), nil +} diff --git a/internal/converter/testdata/array_of_enums.go b/internal/converter/testdata/array_of_enums.go index d7ab881c..5f555e0e 100644 --- a/internal/converter/testdata/array_of_enums.go +++ b/internal/converter/testdata/array_of_enums.go @@ -2,26 +2,45 @@ package testdata const ArrayOfEnums = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "stuff": { - "items": { - "enum": [ - "FOO", - 0, - "BAR", - 1, - "FIZZ", - 2, - "BUZZ", - 3 - ] + "$ref": "#/definitions/ArrayOfEnums", + "definitions": { + "ArrayOfEnums": { + "properties": { + "description": { + "type": "string" + }, + "stuff": { + "items": { + "enum": [ + "FOO", + 0, + "BAR", + 1, + "FIZZ", + 2, + "BUZZ", + 3 + ] + }, + "type": "array" + } }, - "type": "array" + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const ArrayOfEnumsFail = `{ + "description": "something", + "stuff": [ + "FOOZ" + ] +}` + +const ArrayOfEnumsPass = `{ + "description": "something", + "stuff": [ + 3 + ] }` diff --git a/internal/converter/testdata/array_of_messages.go b/internal/converter/testdata/array_of_messages.go index 86d002dd..b91475c2 100644 --- a/internal/converter/testdata/array_of_messages.go +++ b/internal/converter/testdata/array_of_messages.go @@ -2,60 +2,81 @@ package testdata const ArrayOfMessages = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" + "$ref": "#/definitions/ArrayOfMessages", + "definitions": { + "ArrayOfMessages": { + "properties": { + "description": { + "type": "string" + }, + "payload": { + "items": { + "$ref": "#/definitions/samples.PayloadMessage" }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } + "type": "array" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.PayloadMessage": { + "properties": { + "name": { + "type": "string" }, - "additionalProperties": true, - "type": "object" + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } }, - "type": "array" + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const ArrayOfMessagesFail = `{ + "description": "something", + "payload": [ + {"topology": "cruft"} + ] +}` + +const ArrayOfMessagesPass = `{ + "description": "something", + "payload": [ + {"topology": "ARRAY_OF_MESSAGE"} + ] }` diff --git a/internal/converter/testdata/array_of_objects.go b/internal/converter/testdata/array_of_objects.go index 4f1560ea..df71a426 100644 --- a/internal/converter/testdata/array_of_objects.go +++ b/internal/converter/testdata/array_of_objects.go @@ -2,126 +2,151 @@ package testdata const ArrayOfObjects = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { + "$ref": "#/definitions/ArrayOfObjects", + "definitions": { + "ArrayOfObjects": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$ref": "#/definitions/samples.ArrayOfObjects.RepeatedPayload" + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "string" + "type": "object" } ] }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } + "samples.ArrayOfObjects.RepeatedPayload": { + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "array" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ + } +}` + +const ArrayOfObjectsFail = `{ + "description": "something", + "payload": [ { - "type": "null" - }, + "topology": "cruft" + } + ] +}` + +const ArrayOfObjectsPass = `{ + "description": "something", + "payload": [ { - "type": "object" + "topology": "ARRAY_OF_OBJECT" } ] }` diff --git a/internal/converter/testdata/array_of_primitives.go b/internal/converter/testdata/array_of_primitives.go index cb0eb4f0..7d1edd96 100644 --- a/internal/converter/testdata/array_of_primitives.go +++ b/internal/converter/testdata/array_of_primitives.go @@ -2,200 +2,218 @@ package testdata const ArrayOfPrimitives = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" + "$ref": "#/definitions/ArrayOfPrimitives", + "definitions": { + "ArrayOfPrimitives": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "string" + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" + "big_number": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] } - ] - }, - "big_number": { + }, + "additionalProperties": true, "oneOf": [ { - "type": "string" + "type": "null" }, { - "type": "null" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + } }` +const ArrayOfPrimitivesFail = `{"luckyNumbers": ["false"]}` + +const ArrayOfPrimitivesPass = `{"luckyNumbers": [1,2,3]}` + const ArrayOfPrimitivesDouble = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" + "$ref": "#/definitions/ArrayOfPrimitives", + "definitions": { + "ArrayOfPrimitives": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "string" + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "big_number": { - "oneOf": [ - { - "type": "string" + "big_number": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] }, - { - "type": "null" + "bigNumber": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] } - ] - }, - "bigNumber": { + }, + "additionalProperties": true, "oneOf": [ { - "type": "string" + "type": "null" }, { - "type": "null" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + } }` + +const ArrayOfPrimitivesDoubleFail = `{"bigNumber": false}` + +const ArrayOfPrimitivesDoublePass = `{"bigNumber": "2"}` diff --git a/internal/converter/testdata/bytes_payload.go b/internal/converter/testdata/bytes_payload.go index c6738c72..88516647 100644 --- a/internal/converter/testdata/bytes_payload.go +++ b/internal/converter/testdata/bytes_payload.go @@ -2,16 +2,23 @@ package testdata const BytesPayload = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "payload": { - "type": "string", - "format": "binary", - "binaryEncoding": "base64" + "$ref": "#/definitions/BytesPayload", + "definitions": { + "BytesPayload": { + "properties": { + "description": { + "type": "string" + }, + "payload": { + "type": "string", + "format": "binary", + "binaryEncoding": "base64" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const BytesPayloadFail = `{"payload": 12345}` diff --git a/internal/converter/testdata/cyclical_reference.go b/internal/converter/testdata/cyclical_reference.go index 0f39c168..f234fcb9 100644 --- a/internal/converter/testdata/cyclical_reference.go +++ b/internal/converter/testdata/cyclical_reference.go @@ -1,185 +1,203 @@ package testdata -const ( - CyclicalReferenceMessageM = `{ +const CyclicalReferenceMessageM = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "foo": { - "$ref": "samples.Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object", + "$ref": "#/definitions/M", "definitions": { + "M": { + "properties": { + "foo": { + "$ref": "#/definitions/samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Bar": { + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "$ref": "#/definitions/samples.Baz", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "$ref": "#/definitions/samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, "samples.Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "name": { "type": "string" }, "bar": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "$ref": "samples.Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.Bar" }, "type": "array" } }, "additionalProperties": true, - "type": "object", - "id": "samples.Foo" + "type": "object" } } }` - CyclicalReferenceMessageFoo = `{ +const CyclicalReferenceMessageFoo = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo", + "$ref": "#/definitions/Foo", "definitions": { "Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "name": { "type": "string" }, "bar": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "$ref": "Foo", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.Bar" }, "type": "array" } }, "additionalProperties": true, - "type": "object", - "id": "Foo" + "type": "object" + }, + "samples.Bar": { + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "$ref": "#/definitions/samples.Baz", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "$ref": "#/definitions/Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" } } }` - CyclicalReferenceMessageBar = `{ +const CyclicalReferenceMessageBar = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Bar", + "$ref": "#/definitions/Bar", "definitions": { "Bar": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "id": { "type": "integer" }, "baz": { - "properties": { - "enabled": { - "type": "boolean" - }, - "foo": { - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Bar" - }, - "type": "array" - } - }, - "additionalProperties": true, - "type": "object" - } + "$ref": "#/definitions/samples.Baz", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Baz": { + "properties": { + "enabled": { + "type": "boolean" + }, + "foo": { + "$ref": "#/definitions/samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Foo": { + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$ref": "#/definitions/Bar" }, - "additionalProperties": true, - "type": "object" + "type": "array" } }, "additionalProperties": true, - "type": "object", - "id": "Bar" + "type": "object" } } }` - CyclicalReferenceMessageBaz = `{ +const CyclicalReferenceMessageBaz = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Baz", + "$ref": "#/definitions/Baz", "definitions": { "Baz": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "enabled": { "type": "boolean" }, "foo": { - "properties": { - "name": { - "type": "string" - }, - "bar": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "id": { - "type": "integer" - }, - "baz": { - "$ref": "Baz", - "additionalProperties": true - } - }, - "additionalProperties": true, - "type": "object" - }, - "type": "array" - } + "$ref": "#/definitions/samples.Foo", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Bar": { + "properties": { + "id": { + "type": "integer" + }, + "baz": { + "$ref": "#/definitions/Baz", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Foo": { + "properties": { + "name": { + "type": "string" + }, + "bar": { + "items": { + "$ref": "#/definitions/samples.Bar" }, - "additionalProperties": true, - "type": "object" + "type": "array" } }, "additionalProperties": true, - "type": "object", - "id": "Baz" + "type": "object" } } }` -) diff --git a/internal/converter/testdata/enum_ception.go b/internal/converter/testdata/enum_ception.go index 4db6ff01..f49fe07f 100644 --- a/internal/converter/testdata/enum_ception.go +++ b/internal/converter/testdata/enum_ception.go @@ -2,75 +2,76 @@ package testdata const EnumCeption = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "failureMode": { - "enum": [ - "RECURSION_ERROR", - 0, - "SYNTAX_ERROR", - 1 - ], - "oneOf": [ - { + "$ref": "#/definitions/Enumception", + "definitions": { + "Enumception": { + "properties": { + "name": { "type": "string" }, - { - "type": "integer" - } - ] - }, - "payload": { - "$ref": "samples.PayloadMessage", - "additionalProperties": true - }, - "payloads": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "samples.PayloadMessage" - }, - "type": "array" - }, - "importedEnum": { - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { + "timestamp": { "type": "string" }, - { + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "failureMode": { + "enum": [ + "RECURSION_ERROR", + 0, + "SYNTAX_ERROR", + 1 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "payload": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": true + }, + "payloads": { + "items": { + "$ref": "#/definitions/samples.PayloadMessage" + }, + "type": "array" + }, + "importedEnum": { + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] - } - }, - "additionalProperties": true, - "type": "object", - "definitions": { + }, + "additionalProperties": true, + "type": "object" + }, "samples.PayloadMessage": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "name": { "type": "string" @@ -113,8 +114,11 @@ const EnumCeption = `{ } }, "additionalProperties": true, - "type": "object", - "id": "samples.PayloadMessage" + "type": "object" } } }` + +const EnumCeptionFail = `{"payloads": [ {"topology": "MAP"} ]}` + +const EnumCeptionPass = `{"payloads": [ {"topology": "ARRAY_OF_MESSAGE"} ]}` diff --git a/internal/converter/testdata/enum_imported.go b/internal/converter/testdata/enum_imported.go index c15e0869..cf666dea 100644 --- a/internal/converter/testdata/enum_imported.go +++ b/internal/converter/testdata/enum_imported.go @@ -2,28 +2,37 @@ package testdata const EnumImport = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "importedEnum": { - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" + "$ref": "#/definitions/UseImportedEnum", + "definitions": { + "UseImportedEnum": { + "properties": { + "importedEnum": { + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const EnumImportFail = `{"importedEnum": "VALUE_4"}` + +const EnumImportPass = `{"importedEnum": "VALUE_3"}` diff --git a/internal/converter/testdata/enum_nested_reference.go b/internal/converter/testdata/enum_nested_reference.go index 1f456e3b..ae36bc5d 100644 --- a/internal/converter/testdata/enum_nested_reference.go +++ b/internal/converter/testdata/enum_nested_reference.go @@ -2,32 +2,41 @@ package testdata const EnumNestedReference = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "nestedEnumField": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" + "$ref": "#/definitions/Msg", + "definitions": { + "Msg": { + "properties": { + "nestedEnumField": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const EnumNestedReferenceFail = `{"nestedEnumField": 8}` + +const EnumNestedReferencePass = `{"nestedEnumField": "FLAT"}` diff --git a/internal/converter/testdata/enum_with_message.go b/internal/converter/testdata/enum_with_message.go index 68f7548a..82532e5c 100644 --- a/internal/converter/testdata/enum_with_message.go +++ b/internal/converter/testdata/enum_with_message.go @@ -2,26 +2,35 @@ package testdata const EnumWithMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "enumField": { - "enum": [ - "Foo", - 0, - "Bar", - 1, - "Baz", - 2 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" + "$ref": "#/definitions/WithFooBarBaz", + "definitions": { + "WithFooBarBaz": { + "properties": { + "enumField": { + "enum": [ + "Foo", + 0, + "Bar", + 1, + "Baz", + 2 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const EnumWithMessageFail = `{"enumField": 4}` + +const EnumWithMessagePass = `{"enumField": 2}` diff --git a/internal/converter/testdata/field_options.go b/internal/converter/testdata/field_options.go index a5c0b20b..51ca4ae3 100644 --- a/internal/converter/testdata/field_options.go +++ b/internal/converter/testdata/field_options.go @@ -2,17 +2,26 @@ package testdata const FieldOptions = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "ignore": { - "type": "boolean", - "description": "Fields tagged with this will be omitted from generated schemas:" - }, - "required": { - "type": "boolean", - "description": "Fields tagged with this will be marked as \"required\" in generated schemas:" + "$ref": "#/definitions/FieldOptions", + "definitions": { + "FieldOptions": { + "properties": { + "ignore": { + "type": "boolean", + "description": "Fields tagged with this will be omitted from generated schemas:" + }, + "required": { + "type": "boolean", + "description": "Fields tagged with this will be marked as \"required\" in generated schemas:" + } + }, + "additionalProperties": true, + "type": "object", + "description": "Custom FieldOptions:" } - }, - "additionalProperties": true, - "type": "object", - "description": "Custom FieldOptions:" + } }` + +const FieldOptionsFail = `{"ignore": 12345}` + +const FieldOptionsPass = `{"required": true}` diff --git a/internal/converter/testdata/first_enum.go b/internal/converter/testdata/first_enum.go index 3c046a83..85a700f7 100644 --- a/internal/converter/testdata/first_enum.go +++ b/internal/converter/testdata/first_enum.go @@ -21,3 +21,7 @@ const FirstEnum = `{ } ] }` + +const FirstEnumFail = `5` + +const FirstEnumPass = `3` diff --git a/internal/converter/testdata/first_message.go b/internal/converter/testdata/first_message.go index fac59444..a9150070 100644 --- a/internal/converter/testdata/first_message.go +++ b/internal/converter/testdata/first_message.go @@ -2,23 +2,32 @@ package testdata const FirstMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string" - }, - "timestamp1": { - "type": "string" - }, - "id1": { - "type": "integer" - }, - "rating1": { - "type": "number" - }, - "complete1": { - "type": "boolean" + "$ref": "#/definitions/FirstMessage", + "definitions": { + "FirstMessage": { + "properties": { + "name1": { + "type": "string" + }, + "timestamp1": { + "type": "string" + }, + "id1": { + "type": "integer" + }, + "rating1": { + "type": "number" + }, + "complete1": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const FirstMessageFail = `{"complete1": "hello"}` + +const FirstMessagePass = `{"complete1": true}` diff --git a/internal/converter/testdata/google_value.go b/internal/converter/testdata/google_value.go index 6c8b3326..4811d6fa 100644 --- a/internal/converter/testdata/google_value.go +++ b/internal/converter/testdata/google_value.go @@ -2,28 +2,37 @@ package testdata const GoogleValue = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "arg": { - "oneOf": [ - { - "type": "array" - }, - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "object" - }, - { - "type": "string" + "$ref": "#/definitions/GoogleValue", + "definitions": { + "GoogleValue": { + "properties": { + "arg": { + "oneOf": [ + { + "type": "array" + }, + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "object" + }, + { + "type": "string" + } + ], + "description": "` + "`Value`" + ` represents a dynamically typed value which can be either\n null, a number, a string, a boolean, a recursive struct value, or a\n list of values. A producer of value is expected to set one of that\n variants, absence of any variant indicates an error.\n\n The JSON representation for ` + "`Value`" + ` is JSON value." } - ], - "description": "` + "`Value`" + ` represents a dynamically typed value which can be either\n null, a number, a string, a boolean, a recursive struct value, or a\n list of values. A producer of value is expected to set one of that\n variants, absence of any variant indicates an error.\n\n The JSON representation for ` + "`Value`" + ` is JSON value." + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const GoogleValueFail = `{"arg": null}` + +const GoogleValuePass = `{"arg": 12345}` diff --git a/internal/converter/testdata/hidden_fields.go b/internal/converter/testdata/hidden_fields.go index d283fdc9..285e4dad 100644 --- a/internal/converter/testdata/hidden_fields.go +++ b/internal/converter/testdata/hidden_fields.go @@ -2,14 +2,23 @@ package testdata const HiddenFields = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "visible1": { - "type": "string" - }, - "visible2": { - "type": "string" + "$ref": "#/definitions/HiddenFields", + "definitions": { + "HiddenFields": { + "properties": { + "visible1": { + "type": "string" + }, + "visible2": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const HiddenFieldsFail = `{"visible1": 12345}` + +const HiddenFieldsPass = `{"visible2": "hello"}` diff --git a/internal/converter/testdata/imported_enum.go b/internal/converter/testdata/imported_enum.go index fbc17be2..4d8fd2bc 100644 --- a/internal/converter/testdata/imported_enum.go +++ b/internal/converter/testdata/imported_enum.go @@ -21,3 +21,7 @@ const ImportedEnum = `{ } ] }` + +const ImportedEnumFail = `"VALUE_5"` + +const ImportedEnumPass = `"VALUE_3"` diff --git a/internal/converter/testdata/json_fields.go b/internal/converter/testdata/json_fields.go index 13a537f8..ceebcf1c 100644 --- a/internal/converter/testdata/json_fields.go +++ b/internal/converter/testdata/json_fields.go @@ -2,27 +2,35 @@ package testdata const JSONFields = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "identifier": { - "type": "integer" - }, - "someThing": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "snakeNumb": { - "type": "string" + "$ref": "#/definitions/JSONFields", + "definitions": { + "JSONFields": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "identifier": { + "type": "integer" + }, + "someThing": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "snakeNumb": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" -} -` + } +}` + +const JSONFieldsFail = `{"someThing": "onetwothree"}` + +const JSONFieldsPass = `{"someThing": 12345}` diff --git a/internal/converter/testdata/maps.go b/internal/converter/testdata/maps.go index d2d10ea7..11086e55 100644 --- a/internal/converter/testdata/maps.go +++ b/internal/converter/testdata/maps.go @@ -2,68 +2,93 @@ package testdata const Maps = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "map_of_strings": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "map_of_ints": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "map_of_messages": { - "additionalProperties": { - "properties": { - "name": { + "$ref": "#/definitions/Maps", + "definitions": { + "Maps": { + "properties": { + "map_of_strings": { + "additionalProperties": { "type": "string" }, - "timestamp": { - "type": "string" - }, - "id": { + "type": "object" + }, + "map_of_ints": { + "additionalProperties": { "type": "integer" }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" + "type": "object" + }, + "map_of_messages": { + "additionalProperties": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": true }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.PayloadMessage": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" }, - "additionalProperties": true, - "type": "object" + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } }, + "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const MapsFail = `{ + "map_of_strings": { + "one": 1, + "two": 2, + "three": 3 + } +}` + +const MapsPass = `{ + "map_of_strings": { + "one": "1", + "two": "2", + "three": "3" + } }` diff --git a/internal/converter/testdata/message_kind_10.go b/internal/converter/testdata/message_kind_10.go index 40adf170..c8f59c69 100644 --- a/internal/converter/testdata/message_kind_10.go +++ b/internal/converter/testdata/message_kind_10.go @@ -2,24 +2,28 @@ package testdata const MessageKind10 = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" + "$ref": "#/definitions/MessageKind10", + "definitions": { + "MessageKind10": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" -} -` + } +}` diff --git a/internal/converter/testdata/message_kind_11.go b/internal/converter/testdata/message_kind_11.go index 6529e54f..fcf222fd 100644 --- a/internal/converter/testdata/message_kind_11.go +++ b/internal/converter/testdata/message_kind_11.go @@ -2,36 +2,57 @@ package testdata const MessageKind11 = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" + "$ref": "#/definitions/MessageKind11", + "definitions": { + "MessageKind11": { + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$ref": "#/definitions/samples.MessageKind1" }, - "complete": { - "type": "boolean" - } + "type": "array" + }, + "kind2": { + "$ref": "#/definitions/samples.MessageKind2", + "additionalProperties": true }, - "additionalProperties": true, - "type": "object" + "kind3": { + "$ref": "#/definitions/samples.MessageKind3", + "additionalProperties": true + }, + "kind4": { + "$ref": "#/definitions/samples.MessageKind4", + "additionalProperties": true + } }, - "type": "array" + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind1": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" }, - "kind2": { + "samples.MessageKind2": { "properties": { "name": { "type": "string" @@ -58,7 +79,7 @@ const MessageKind11 = `{ "additionalProperties": true, "type": "object" }, - "kind3": { + "samples.MessageKind3": { "properties": { "name": { "type": "string" @@ -82,7 +103,7 @@ const MessageKind11 = `{ "additionalProperties": true, "type": "object" }, - "kind4": { + "samples.MessageKind4": { "properties": { "name": { "type": "string" @@ -106,8 +127,5 @@ const MessageKind11 = `{ "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" -} -` + } +}` diff --git a/internal/converter/testdata/message_kind_12.go b/internal/converter/testdata/message_kind_12.go index 0743a51d..0536eb3f 100644 --- a/internal/converter/testdata/message_kind_12.go +++ b/internal/converter/testdata/message_kind_12.go @@ -2,120 +2,157 @@ package testdata const MessageKind12 = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" + "$ref": "#/definitions/MessageKind12", + "definitions": { + "MessageKind12": { + "properties": { + "name": { + "type": "string" + }, + "f": { + "$ref": "#/definitions/samples.MessageKind11", + "additionalProperties": true + }, + "kind5": { + "$ref": "#/definitions/samples.MessageKind5", + "additionalProperties": true + }, + "kind6": { + "$ref": "#/definitions/samples.MessageKind6", + "additionalProperties": true + }, + "kind7": { + "$ref": "#/definitions/samples.MessageKind7", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" }, - "f": { + "samples.MessageKind1": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind11": { "properties": { "name": { "type": "string" }, "ones": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind1" }, "type": "array" }, "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind2", + "additionalProperties": true }, "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind3", + "additionalProperties": true }, "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind4", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" } }, "additionalProperties": true, "type": "object" }, - "kind5": { + "samples.MessageKind5": { "properties": { "name": { "type": "string" @@ -139,7 +176,7 @@ const MessageKind12 = `{ "additionalProperties": true, "type": "object" }, - "kind6": { + "samples.MessageKind6": { "properties": { "name": { "type": "string" @@ -163,7 +200,7 @@ const MessageKind12 = `{ "additionalProperties": true, "type": "object" }, - "kind7": { + "samples.MessageKind7": { "properties": { "name": { "type": "string" @@ -187,8 +224,5 @@ const MessageKind12 = `{ "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" -} -` + } +}` diff --git a/internal/converter/testdata/message_with_comments.go b/internal/converter/testdata/message_with_comments.go index b14b869b..23f3b304 100644 --- a/internal/converter/testdata/message_with_comments.go +++ b/internal/converter/testdata/message_with_comments.go @@ -2,13 +2,20 @@ package testdata const MessageWithComments = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string", - "description": "This field is supposed to represent blahblahblah" + "$ref": "#/definitions/MessageWithComments", + "definitions": { + "MessageWithComments": { + "properties": { + "name1": { + "type": "string", + "description": "This field is supposed to represent blahblahblah" + } + }, + "additionalProperties": true, + "type": "object", + "description": "This is a message level comment and talks about what this message is and why you should care about it!" } - }, - "additionalProperties": true, - "type": "object", - "description": "This is a message level comment and talks about what this message is and why you should care about it!" + } }` + +const MessageWithCommentsFail = `{"name1": 12345}` diff --git a/internal/converter/testdata/nested_message.go b/internal/converter/testdata/nested_message.go index 15dba579..61ba7034 100644 --- a/internal/converter/testdata/nested_message.go +++ b/internal/converter/testdata/nested_message.go @@ -2,8 +2,22 @@ package testdata const NestedMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { + "$ref": "#/definitions/NestedMessage", + "definitions": { + "NestedMessage": { + "properties": { + "payload": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": true + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.PayloadMessage": { "properties": { "name": { "type": "string" @@ -47,11 +61,18 @@ const NestedMessage = `{ }, "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const NestedMessageFail = `{ + "payload": { + "topology": "ROUND" + } +}` + +const NestedMessagePass = `{ + "payload": { + "topology": "FLAT" + } }` diff --git a/internal/converter/testdata/nested_object.go b/internal/converter/testdata/nested_object.go index 3becb18d..60e30058 100644 --- a/internal/converter/testdata/nested_object.go +++ b/internal/converter/testdata/nested_object.go @@ -2,8 +2,22 @@ package testdata const NestedObject = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { + "$ref": "#/definitions/NestedObject", + "definitions": { + "NestedObject": { + "properties": { + "payload": { + "$ref": "#/definitions/samples.NestedObject.NestedPayload", + "additionalProperties": true + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.NestedObject.NestedPayload": { "properties": { "name": { "type": "string" @@ -47,11 +61,14 @@ const NestedObject = `{ }, "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const NestedObjectFail = `{"payload": false}` + +const NestedObjectPass = `{ + "payload": { + "topology": "NESTED_OBJECT" + } }` diff --git a/internal/converter/testdata/oneof.go b/internal/converter/testdata/oneof.go index 7ca433a4..f2fb77a6 100644 --- a/internal/converter/testdata/oneof.go +++ b/internal/converter/testdata/oneof.go @@ -2,11 +2,38 @@ package testdata const OneOf = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "something" - ], - "properties": { - "bar": { + "$ref": "#/definitions/OneOf", + "definitions": { + "OneOf": { + "properties": { + "bar": { + "$ref": "#/definitions/samples.OneOf.Bar", + "additionalProperties": true + }, + "baz": { + "$ref": "#/definitions/samples.OneOf.Baz", + "additionalProperties": true + }, + "something": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object", + "oneOf": [ + { + "required": [ + "bar" + ] + }, + { + "required": [ + "baz" + ] + } + ] + }, + "samples.OneOf.Bar": { "required": [ "foo" ], @@ -18,7 +45,7 @@ const OneOf = `{ "additionalProperties": true, "type": "object" }, - "baz": { + "samples.OneOf.Baz": { "required": [ "foo" ], @@ -29,23 +56,17 @@ const OneOf = `{ }, "additionalProperties": true, "type": "object" - }, - "something": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object", - "oneOf": [ - { - "required": [ - "bar" - ] - }, - { - "required": [ - "baz" - ] } - ] + } +}` + +const OneOfFail = `{ + "something": true, + "bar": {"foo": 1}, + "baz": {"foo": "one"} +}` + +const OneOfPass = `{ + "something": true, + "bar": {"foo": 1} }` diff --git a/internal/converter/testdata/payload_message.go b/internal/converter/testdata/payload_message.go index 8cf27a4e..ce718a7f 100644 --- a/internal/converter/testdata/payload_message.go +++ b/internal/converter/testdata/payload_message.go @@ -2,47 +2,56 @@ package testdata const PayloadMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { + "$ref": "#/definitions/PayloadMessage", + "definitions": { + "PayloadMessage": { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const PayloadMessageFail = `{"topology": "MAP"}` + +const PayloadMessagePass = `{"topology": "ARRAY_OF_MESSAGE"}` diff --git a/internal/converter/testdata/payload_message_2.go b/internal/converter/testdata/payload_message_2.go index 69e7730c..5af2c8ec 100644 --- a/internal/converter/testdata/payload_message_2.go +++ b/internal/converter/testdata/payload_message_2.go @@ -2,55 +2,72 @@ package testdata const PayloadMessage2 = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "timestamp", - "id", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 + "$ref": "#/definitions/PayloadMessage2", + "definitions": { + "PayloadMessage2": { + "required": [ + "name", + "timestamp", + "id", + "rating", + "complete", + "topology" ], - "oneOf": [ - { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const PayloadMessage2Fail = `{ +}` + +const PayloadMessage2Pass = `{ + "name": "test", + "timestamp": "1970-01-01T00:00:00Z", + "id": 1, + "rating": 100, + "complete": true, + "topology": "FLAT" }` diff --git a/internal/converter/testdata/proto2_nested_message.go b/internal/converter/testdata/proto2_nested_message.go index 018ca62f..1263de94 100644 --- a/internal/converter/testdata/proto2_nested_message.go +++ b/internal/converter/testdata/proto2_nested_message.go @@ -2,11 +2,25 @@ package testdata const Proto2NestedMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload" - ], - "properties": { - "payload": { + "$ref": "#/definitions/Proto2NestedMessage", + "definitions": { + "Proto2NestedMessage": { + "required": [ + "payload" + ], + "properties": { + "payload": { + "$ref": "#/definitions/samples.Proto2PayloadMessage", + "additionalProperties": false + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Proto2PayloadMessage": { "required": [ "name", "id" @@ -52,13 +66,22 @@ const Proto2NestedMessage = `{ ] } }, - "additionalProperties": false, + "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const Proto2NestedMessageFail = `{ + "payload": { + "topology": "FLAT" + } +}` + +const Proto2NestedMessagePass = `{ + "payload": { + "id": 1, + "name": "something", + "topology": "FLAT" + } }` diff --git a/internal/converter/testdata/proto2_nested_object.go b/internal/converter/testdata/proto2_nested_object.go index dea5b2a9..9bf0f590 100644 --- a/internal/converter/testdata/proto2_nested_object.go +++ b/internal/converter/testdata/proto2_nested_object.go @@ -2,12 +2,26 @@ package testdata const Proto2NestedObject = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload", - "description" - ], - "properties": { - "payload": { + "$ref": "#/definitions/Proto2NestedObject", + "definitions": { + "Proto2NestedObject": { + "required": [ + "payload", + "description" + ], + "properties": { + "payload": { + "$ref": "#/definitions/samples.Proto2NestedObject.NestedPayload", + "additionalProperties": false + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Proto2NestedObject.NestedPayload": { "required": [ "name", "timestamp", @@ -57,13 +71,26 @@ const Proto2NestedObject = `{ ] } }, - "additionalProperties": false, + "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const Proto2NestedObjectFail = `{ + "payload": { + "topology": "FLAT" + } +}` + +const Proto2NestedObjectPass = `{ + "description": "lots of attributes", + "payload": { + "name": "something", + "timestamp": "1970-01-01T00:00:00Z", + "id": 1, + "rating": 100, + "complete": true, + "topology": "FLAT" + } }` diff --git a/internal/converter/testdata/proto2_payload_message.go b/internal/converter/testdata/proto2_payload_message.go index ba780c16..031579bb 100644 --- a/internal/converter/testdata/proto2_payload_message.go +++ b/internal/converter/testdata/proto2_payload_message.go @@ -2,51 +2,66 @@ package testdata const Proto2PayloadMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 + "$ref": "#/definitions/Proto2PayloadMessage", + "definitions": { + "Proto2PayloadMessage": { + "required": [ + "name", + "id" ], - "oneOf": [ - { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const Proto2PayloadMessageFail = `{ + "complete": false +}` + +const Proto2PayloadMessagePass = `{ + "id": 1, + "name": "something", + "topology": "FLAT" }` diff --git a/internal/converter/testdata/proto2_required.go b/internal/converter/testdata/proto2_required.go index 24c4d80e..3a35f816 100644 --- a/internal/converter/testdata/proto2_required.go +++ b/internal/converter/testdata/proto2_required.go @@ -2,20 +2,34 @@ package testdata const Proto2Required = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" + "$ref": "#/definitions/Proto2Required", + "definitions": { + "Proto2Required": { + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const Proto2RequiredFail = `{ + "page_number": 4 +}` + +const Proto2RequiredPass = `{ + "query": "what?", + "page_number": 4 }` diff --git a/internal/converter/testdata/proto3_required.go b/internal/converter/testdata/proto3_required.go index 1ace9432..e545d695 100644 --- a/internal/converter/testdata/proto3_required.go +++ b/internal/converter/testdata/proto3_required.go @@ -2,21 +2,35 @@ package testdata const Proto3Required = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query", - "page_number" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" + "$ref": "#/definitions/Proto3Required", + "definitions": { + "Proto3Required": { + "required": [ + "query", + "page_number" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } +}` + +const Proto3RequiredFail = `{ + "page_number": 4 +}` + +const Proto3RequiredPass = `{ + "query": "what?", + "page_number": 4 }` diff --git a/internal/converter/testdata/second_enum.go b/internal/converter/testdata/second_enum.go index e3142f77..066e097a 100644 --- a/internal/converter/testdata/second_enum.go +++ b/internal/converter/testdata/second_enum.go @@ -21,3 +21,7 @@ const SecondEnum = `{ } ] }` + +const SecondEnumFail = `"VALUE_3"` + +const SecondEnumPass = `"VALUE_7"` diff --git a/internal/converter/testdata/second_message.go b/internal/converter/testdata/second_message.go index a66933ef..63120c32 100644 --- a/internal/converter/testdata/second_message.go +++ b/internal/converter/testdata/second_message.go @@ -2,23 +2,32 @@ package testdata const SecondMessage = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name2": { - "type": "string" - }, - "timestamp2": { - "type": "string" - }, - "id2": { - "type": "integer" - }, - "rating2": { - "type": "number" - }, - "complete2": { - "type": "boolean" + "$ref": "#/definitions/SecondMessage", + "definitions": { + "SecondMessage": { + "properties": { + "name2": { + "type": "string" + }, + "timestamp2": { + "type": "string" + }, + "id2": { + "type": "integer" + }, + "rating2": { + "type": "number" + }, + "complete2": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const SecondMessageFail = `{"complete2": "hello"}` + +const SecondMessagePass = `{"complete2": true}` diff --git a/internal/converter/testdata/self_reference.go b/internal/converter/testdata/self_reference.go index 234be705..dc5a0e58 100644 --- a/internal/converter/testdata/self_reference.go +++ b/internal/converter/testdata/self_reference.go @@ -2,25 +2,43 @@ package testdata const SelfReference = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo", + "$ref": "#/definitions/Foo", "definitions": { "Foo": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "name": { "type": "string" }, "bar": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "Foo" + "$ref": "#/definitions/Foo" }, "type": "array" } }, "additionalProperties": true, - "type": "object", - "id": "Foo" + "type": "object" } } }` + +const SelfReferenceFail = `{ + "bar": [ + { + "name": false + } + ] +}` + +const SelfReferencePass = `{ + "bar": [ + { + "name": "referenced-bar", + "bar": [ + { + "name": "barception" + } + ] + } + ] +}` diff --git a/internal/converter/testdata/timestamp.go b/internal/converter/testdata/timestamp.go index 9ac21622..01a4e699 100644 --- a/internal/converter/testdata/timestamp.go +++ b/internal/converter/testdata/timestamp.go @@ -2,12 +2,21 @@ package testdata const Timestamp = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" + "$ref": "#/definitions/Timestamp", + "definitions": { + "Timestamp": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const TimestampFail = `{"timestamp": "twelve oclock"}` + +const TimestampPass = `{"timestamp": "1970-01-01T00:00:00Z"}` diff --git a/internal/converter/testdata/wellknown.go b/internal/converter/testdata/wellknown.go index 1fc75eb8..9bd8ea60 100644 --- a/internal/converter/testdata/wellknown.go +++ b/internal/converter/testdata/wellknown.go @@ -2,38 +2,47 @@ package testdata const WellKnown = `{ "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "string_value": { - "additionalProperties": true, - "type": "string" - }, - "map_of_integers": { - "additionalProperties": { - "additionalProperties": true, - "type": "integer" - }, - "type": "object" - }, - "map_of_scalar_integers": { - "additionalProperties": { - "type": "integer" + "$ref": "#/definitions/WellKnown", + "definitions": { + "WellKnown": { + "properties": { + "string_value": { + "additionalProperties": true, + "type": "string" + }, + "map_of_integers": { + "additionalProperties": { + "additionalProperties": true, + "type": "integer" + }, + "type": "object" + }, + "map_of_scalar_integers": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "list_of_integers": { + "items": { + "type": "integer", + "description": "Wrapper message for ` + "`int32`" + `.\n\n The JSON representation for ` + "`Int32Value`" + ` is JSON number." + }, + "type": "array" + }, + "duration": { + "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)s$", + "type": "string", + "description": "This is a duration:", + "format": "regex" + } }, + "additionalProperties": true, "type": "object" - }, - "list_of_integers": { - "items": { - "type": "integer", - "description": "Wrapper message for ` + "`int32`" + `.\n\n The JSON representation for ` + "`Int32Value`" + ` is JSON number." - }, - "type": "array" - }, - "duration": { - "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)s$", - "type": "string", - "description": "This is a duration:", - "format": "regex" } - }, - "additionalProperties": true, - "type": "object" + } }` + +const WellKnownFail = `{"duration": "9"}` + +const WellKnownPass = `{"duration": "9s"}` diff --git a/internal/converter/types.go b/internal/converter/types.go index 6dcd1d0a..8812a14e 100644 --- a/internal/converter/types.go +++ b/internal/converter/types.go @@ -71,6 +71,7 @@ func (c *Converter) registerType(pkgName *string, msg *descriptor.DescriptorProt // Convert a proto "field" (essentially a type-switch with some recursion): func (c *Converter) convertField(curPkg *ProtoPackage, desc *descriptor.FieldDescriptorProto, msg *descriptor.DescriptorProto, duplicatedMessages map[*descriptor.DescriptorProto]string) (*jsonschema.Type, error) { + // Prepare a new jsonschema.Type for our eventual return value: jsonSchemaType := &jsonschema.Type{} @@ -256,6 +257,10 @@ func (c *Converter) convertField(curPkg *ProtoPackage, desc *descriptor.FieldDes WithField("msg_name", *msg.Name). Tracef("Is a map") + if recursedJSONSchemaType.Properties == nil { + return nil, fmt.Errorf("Unable to find properties of MAP type") + } + // Make sure we have a "value": value, valuePresent := recursedJSONSchemaType.Properties.Get("value") if !valuePresent { @@ -326,19 +331,13 @@ func (c *Converter) convertField(curPkg *ProtoPackage, desc *descriptor.FieldDes // Converts a proto "MESSAGE" into a JSON-Schema: func (c *Converter) convertMessageType(curPkg *ProtoPackage, msg *descriptor.DescriptorProto) (*jsonschema.Schema, error) { - // first, recursively find messages that appear more than once - in particular, that will break cycles - duplicatedMessages, err := c.findDuplicatedNestedMessages(curPkg, msg) - if err != nil { - return nil, err - } - - // main schema for the message - rootType, err := c.recursiveConvertMessageType(curPkg, msg, "", duplicatedMessages, false) + // Get a list of any nested messages in our schema: + duplicatedMessages, err := c.findNestedMessages(curPkg, msg) if err != nil { return nil, err } - // and then generate the sub-schema for each duplicated message + // Build up a list of JSONSchema type definitions for every message: definitions := jsonschema.Definitions{} for refMsg, name := range duplicatedMessages { refType, err := c.recursiveConvertMessageType(curPkg, refMsg, "", duplicatedMessages, true) @@ -346,63 +345,48 @@ func (c *Converter) convertMessageType(curPkg *ProtoPackage, msg *descriptor.Des return nil, err } - // need to give that schema an ID - if refType.Extras == nil { - refType.Extras = make(map[string]interface{}) - } - refType.Extras["id"] = name + // Add the schema to our definitions: definitions[name] = refType } + // Put together a JSON schema with our discovered definitions, and a $ref for the root type: newJSONSchema := &jsonschema.Schema{ - Type: rootType, + Type: &jsonschema.Type{ + Ref: fmt.Sprintf("%s%s", c.refPrefix, msg.GetName()), + Version: jsonschema.Version, + }, Definitions: definitions, } - // Look for required fields (either by proto2 required flag, or the AllFieldsRequired option): - for _, fieldDesc := range msg.GetField() { - if (c.Flags.AllFieldsRequired && fieldDesc.OneofIndex == nil) || fieldDesc.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REQUIRED { - newJSONSchema.Required = append(newJSONSchema.Required, fieldDesc.GetName()) - } - } - - newJSONSchema.Required = dedupe(newJSONSchema.Required) - return newJSONSchema, nil } -// findDuplicatedNestedMessages takes a message, and returns a map mapping pointers to messages that appear more than once -// (typically because they're part of a reference cycle) to the sub-schema name that we give them. -func (c *Converter) findDuplicatedNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto) (map[*descriptor.DescriptorProto]string, error) { - all := make(map[*descriptor.DescriptorProto]*nameAndCounter) - if err := c.recursiveFindDuplicatedNestedMessages(curPkg, msg, msg.GetName(), all); err != nil { +// findNestedMessages takes a message, and returns a map mapping pointers to messages nested within it: +// these messages become definitions which can be referenced (instead of repeating them every time they're used) +func (c *Converter) findNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto) (map[*descriptor.DescriptorProto]string, error) { + + // Get a list of all nested messages, and how often they occur: + nestedMessages := make(map[*descriptor.DescriptorProto]string) + if err := c.recursiveFindNestedMessages(curPkg, msg, msg.GetName(), nestedMessages); err != nil { return nil, err } + // Now filter them: result := make(map[*descriptor.DescriptorProto]string) - for m, nameAndCounter := range all { - if nameAndCounter.counter > 1 && !strings.HasPrefix(nameAndCounter.name, ".google.protobuf.") { - result[m] = strings.TrimLeft(nameAndCounter.name, ".") + for message, messageName := range nestedMessages { + if !message.GetOptions().GetMapEntry() && !strings.HasPrefix(messageName, ".google.protobuf.") { + result[message] = strings.TrimLeft(messageName, ".") } } return result, nil } -type nameAndCounter struct { - name string - counter int -} - -func (c *Converter) recursiveFindDuplicatedNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto, typeName string, alreadySeen map[*descriptor.DescriptorProto]*nameAndCounter) error { - if nameAndCounter, present := alreadySeen[msg]; present { - nameAndCounter.counter++ +func (c *Converter) recursiveFindNestedMessages(curPkg *ProtoPackage, msg *descriptor.DescriptorProto, typeName string, nestedMessages map[*descriptor.DescriptorProto]string) error { + if _, present := nestedMessages[msg]; present { return nil } - alreadySeen[msg] = &nameAndCounter{ - name: typeName, - counter: 1, - } + nestedMessages[msg] = typeName for _, desc := range msg.GetField() { descType := desc.GetType() @@ -416,7 +400,7 @@ func (c *Converter) recursiveFindDuplicatedNestedMessages(curPkg *ProtoPackage, if !ok { return fmt.Errorf("no such message type named %s", typeName) } - if err := c.recursiveFindDuplicatedNestedMessages(curPkg, recordType, typeName, alreadySeen); err != nil { + if err := c.recursiveFindNestedMessages(curPkg, recordType, typeName, nestedMessages); err != nil { return err } } @@ -469,12 +453,11 @@ func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msg *descr // Set defaults: jsonSchemaType.Properties = orderedmap.New() - jsonSchemaType.Version = jsonschema.Version + // Look up references: if refName, ok := duplicatedMessages[msg]; ok && !ignoreDuplicatedMessages { return &jsonschema.Type{ - Version: jsonschema.Version, - Ref: refName, + Ref: fmt.Sprintf("%s%s", c.refPrefix, refName), }, nil } @@ -500,8 +483,8 @@ func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msg *descr // Check for our custom field options: opts := fieldDesc.GetOptions() - if opts != nil && proto.HasExtension(opts, protos.E_Options) { - opt, err := proto.GetExtension(opts, protos.E_Options) + if opts != nil && proto.HasExtension(opts, protos.E_FieldOptions) { + opt, err := proto.GetExtension(opts, protos.E_FieldOptions) if err == nil { if fieldOptions, ok := opt.(*protos.FieldOptions); ok { diff --git a/internal/protos/options.pb.go b/internal/protos/options.pb.go index de51e01e..15ba33ee 100644 --- a/internal/protos/options.pb.go +++ b/internal/protos/options.pb.go @@ -1,3 +1,7 @@ +// Custom options for protoc-gen-jsonschema +// Allocated range is 1125-1129 +// See https://github.com/protocolbuffers/protobuf/blob/master/docs/options.md + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 @@ -21,7 +25,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// Custom FieldOptions for protoc-gen-jsonschema: +// Custom FieldOptions: type FieldOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -84,16 +88,16 @@ var file_options_proto_extTypes = []protoimpl.ExtensionInfo{ ExtendedType: (*descriptor.FieldOptions)(nil), ExtensionType: (*FieldOptions)(nil), Field: 1125, - Name: "protoc.gen.jsonschema.options", - Tag: "bytes,1125,opt,name=options", + Name: "protoc.gen.jsonschema.field_options", + Tag: "bytes,1125,opt,name=field_options", Filename: "options.proto", }, } // Extension fields to descriptor.FieldOptions. var ( - // optional protoc.gen.jsonschema.FieldOptions options = 1125; - E_Options = &file_options_proto_extTypes[0] + // optional protoc.gen.jsonschema.FieldOptions field_options = 1125; + E_FieldOptions = &file_options_proto_extTypes[0] ) var File_options_proto protoreflect.FileDescriptor @@ -107,14 +111,15 @@ var file_options_proto_rawDesc = []byte{ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x3a, 0x5d, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe5, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x67, 0x65, 0x6e, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a, 0x5a, 0x08, 0x2e, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x3a, 0x68, 0x0a, 0x0d, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe5, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x67, 0x65, 0x6e, + 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -135,8 +140,8 @@ var file_options_proto_goTypes = []interface{}{ (*descriptor.FieldOptions)(nil), // 1: google.protobuf.FieldOptions } var file_options_proto_depIdxs = []int32{ - 1, // 0: protoc.gen.jsonschema.options:extendee -> google.protobuf.FieldOptions - 0, // 1: protoc.gen.jsonschema.options:type_name -> protoc.gen.jsonschema.FieldOptions + 1, // 0: protoc.gen.jsonschema.field_options:extendee -> google.protobuf.FieldOptions + 0, // 1: protoc.gen.jsonschema.field_options:type_name -> protoc.gen.jsonschema.FieldOptions 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 1, // [1:2] is the sub-list for extension type_name diff --git a/jsonschemas/ArrayOfEnums.jsonschema b/jsonschemas/ArrayOfEnums.jsonschema index c393d887..7b0f3dd9 100644 --- a/jsonschemas/ArrayOfEnums.jsonschema +++ b/jsonschemas/ArrayOfEnums.jsonschema @@ -1,25 +1,30 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "type": "string" - }, - "stuff": { - "items": { - "enum": [ - "FOO", - 0, - "BAR", - 1, - "FIZZ", - 2, - "BUZZ", - 3 - ] + "$ref": "#/definitions/ArrayOfEnums", + "definitions": { + "ArrayOfEnums": { + "properties": { + "description": { + "type": "string" + }, + "stuff": { + "items": { + "enum": [ + "FOO", + 0, + "BAR", + 1, + "FIZZ", + 2, + "BUZZ", + 3 + ] + }, + "type": "array" + } }, - "type": "array" + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/ArrayOfMessages.jsonschema b/jsonschemas/ArrayOfMessages.jsonschema index 3f7ea01b..9e99c051 100644 --- a/jsonschemas/ArrayOfMessages.jsonschema +++ b/jsonschemas/ArrayOfMessages.jsonschema @@ -1,125 +1,132 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { + "$ref": "#/definitions/ArrayOfMessages", + "definitions": { + "ArrayOfMessages": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$ref": "#/definitions/samples.PayloadMessage" + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "string" + "type": "object" } ] }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } + "samples.PayloadMessage": { + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "array" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + } } \ No newline at end of file diff --git a/jsonschemas/ArrayOfObjects.jsonschema b/jsonschemas/ArrayOfObjects.jsonschema index 3f7ea01b..ba553b48 100644 --- a/jsonschemas/ArrayOfObjects.jsonschema +++ b/jsonschemas/ArrayOfObjects.jsonschema @@ -1,125 +1,132 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { + "$ref": "#/definitions/ArrayOfObjects", + "definitions": { + "ArrayOfObjects": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "payload": { + "items": { + "$ref": "#/definitions/samples.ArrayOfObjects.RepeatedPayload" + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "string" + "type": "object" } ] }, - "payload": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "id": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "rating": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "complete": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - }, - { - "type": "null" - } - ] - } + "samples.ArrayOfObjects.RepeatedPayload": { + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + "timestamp": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "rating": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "number" + } + ] + }, + "complete": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "boolean" + } + ] + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ] + } }, + "additionalProperties": true, "oneOf": [ { "type": "null" }, { - "type": "array" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + } } \ No newline at end of file diff --git a/jsonschemas/ArrayOfPrimitives.jsonschema b/jsonschemas/ArrayOfPrimitives.jsonschema index e3cfdc11..c7375142 100644 --- a/jsonschemas/ArrayOfPrimitives.jsonschema +++ b/jsonschemas/ArrayOfPrimitives.jsonschema @@ -1,94 +1,99 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "description": { - "oneOf": [ - { - "type": "null" + "$ref": "#/definitions/ArrayOfPrimitives", + "definitions": { + "ArrayOfPrimitives": { + "properties": { + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "luckyNumbers": { - "items": { - "oneOf": [ - { - "type": "null" + "luckyNumbers": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] }, - { - "type": "integer" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "luckyBigNumbers": { - "items": { - "oneOf": [ - { - "type": "string" + "luckyBigNumbers": { + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] }, - { - "type": "null" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" - } - ] - }, - "keyWords": { - "items": { - "oneOf": [ - { - "type": "null" + "keyWords": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] }, - { - "type": "string" - } - ] - }, - "oneOf": [ - { - "type": "null" + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] }, - { - "type": "array" + "big_number": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] } - ] - }, - "big_number": { + }, + "additionalProperties": true, "oneOf": [ { - "type": "string" + "type": "null" }, { - "type": "null" + "type": "object" } ] } - }, - "additionalProperties": true, - "oneOf": [ - { - "type": "null" - }, - { - "type": "object" - } - ] + } } \ No newline at end of file diff --git a/jsonschemas/Enumception.jsonschema b/jsonschemas/Enumception.jsonschema index 315afb68..60b145b5 100644 --- a/jsonschemas/Enumception.jsonschema +++ b/jsonschemas/Enumception.jsonschema @@ -1,75 +1,76 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "failureMode": { - "enum": [ - "RECURSION_ERROR", - 0, - "SYNTAX_ERROR", - 1 - ], - "oneOf": [ - { + "$ref": "#/definitions/Enumception", + "definitions": { + "Enumception": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { "type": "string" }, - { + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "failureMode": { + "enum": [ + "RECURSION_ERROR", + 0, + "SYNTAX_ERROR", + 1 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "payload": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": false + }, + "payloads": { + "items": { + "$ref": "#/definitions/samples.PayloadMessage" + }, + "additionalProperties": false, + "type": "array" + }, + "importedEnum": { + "enum": [ + "VALUE_0", + 0, + "VALUE_1", + 1, + "VALUE_2", + 2, + "VALUE_3", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] - }, - "payload": { - "$ref": "samples.PayloadMessage", - "additionalProperties": false - }, - "payloads": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "$ref": "samples.PayloadMessage" }, "additionalProperties": false, - "type": "array" + "type": "object" }, - "importedEnum": { - "enum": [ - "VALUE_0", - 0, - "VALUE_1", - 1, - "VALUE_2", - 2, - "VALUE_3", - 3 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } - }, - "additionalProperties": false, - "type": "object", - "definitions": { "samples.PayloadMessage": { - "$schema": "http://json-schema.org/draft-04/schema#", "properties": { "name": { "type": "string" @@ -112,8 +113,7 @@ } }, "additionalProperties": false, - "type": "object", - "id": "samples.PayloadMessage" + "type": "object" } } } \ No newline at end of file diff --git a/jsonschemas/FirstMessage.jsonschema b/jsonschemas/FirstMessage.jsonschema index 55b54424..6cbb43eb 100644 --- a/jsonschemas/FirstMessage.jsonschema +++ b/jsonschemas/FirstMessage.jsonschema @@ -1,22 +1,27 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string" - }, - "timestamp1": { - "type": "string" - }, - "id1": { - "type": "integer" - }, - "rating1": { - "type": "number" - }, - "complete1": { - "type": "boolean" + "$ref": "#/definitions/FirstMessage", + "definitions": { + "FirstMessage": { + "properties": { + "name1": { + "type": "string" + }, + "timestamp1": { + "type": "string" + }, + "id1": { + "type": "integer" + }, + "rating1": { + "type": "number" + }, + "complete1": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/GoogleValue.jsonschema b/jsonschemas/GoogleValue.jsonschema index 709e6bd5..8bbcdb13 100644 --- a/jsonschemas/GoogleValue.jsonschema +++ b/jsonschemas/GoogleValue.jsonschema @@ -1,27 +1,32 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "arg": { - "oneOf": [ - { - "type": "array" - }, - { - "type": "boolean" - }, - { - "type": "number" - }, - { - "type": "object" - }, - { - "type": "string" + "$ref": "#/definitions/GoogleValue", + "definitions": { + "GoogleValue": { + "properties": { + "arg": { + "oneOf": [ + { + "type": "array" + }, + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "object" + }, + { + "type": "string" + } + ], + "description": "`Value` represents a dynamically typed value which can be either\n null, a number, a string, a boolean, a recursive struct value, or a\n list of values. A producer of value is expected to set one of that\n variants, absence of any variant indicates an error.\n\n The JSON representation for `Value` is JSON value." } - ], - "description": "`Value` represents a dynamically typed value which can be either\n null, a number, a string, a boolean, a recursive struct value, or a\n list of values. A producer of value is expected to set one of that\n variants, absence of any variant indicates an error.\n\n The JSON representation for `Value` is JSON value." + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/HiddenFields.jsonschema b/jsonschemas/HiddenFields.jsonschema index 043da7ab..9ba3aca6 100644 --- a/jsonschemas/HiddenFields.jsonschema +++ b/jsonschemas/HiddenFields.jsonschema @@ -1,13 +1,18 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "visible1": { - "type": "string" - }, - "visible2": { - "type": "string" + "$ref": "#/definitions/HiddenFields", + "definitions": { + "HiddenFields": { + "properties": { + "visible1": { + "type": "string" + }, + "visible2": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/JSONFields.jsonschema b/jsonschemas/JSONFields.jsonschema index 7624fcea..d6393f97 100644 --- a/jsonschemas/JSONFields.jsonschema +++ b/jsonschemas/JSONFields.jsonschema @@ -1,25 +1,30 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "identifier": { - "type": "integer" - }, - "someThing": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "snakeNumb": { - "type": "string" + "$ref": "#/definitions/JSONFields", + "definitions": { + "JSONFields": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "identifier": { + "type": "integer" + }, + "someThing": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "snakeNumb": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Maps.jsonschema b/jsonschemas/Maps.jsonschema index 1ca1a252..f59b3f01 100644 --- a/jsonschemas/Maps.jsonschema +++ b/jsonschemas/Maps.jsonschema @@ -1,67 +1,76 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "map_of_strings": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "map_of_ints": { - "additionalProperties": { - "type": "integer" - }, - "type": "object" - }, - "map_of_messages": { - "additionalProperties": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { + "$ref": "#/definitions/Maps", + "definitions": { + "Maps": { + "properties": { + "map_of_strings": { + "additionalProperties": { "type": "string" }, - "id": { + "type": "object" + }, + "map_of_ints": { + "additionalProperties": { "type": "integer" }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" + "type": "object" + }, + "map_of_messages": { + "additionalProperties": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": true }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer" - } - ] - } + "type": "object" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.PayloadMessage": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" }, - "additionalProperties": true, - "type": "object" + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + } }, + "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/MessageKind10.jsonschema b/jsonschemas/MessageKind10.jsonschema index 827aac00..581271ac 100644 --- a/jsonschemas/MessageKind10.jsonschema +++ b/jsonschemas/MessageKind10.jsonschema @@ -1,22 +1,27 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" + "$ref": "#/definitions/MessageKind10", + "definitions": { + "MessageKind10": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/MessageKind11.jsonschema b/jsonschemas/MessageKind11.jsonschema index 19dd2f0a..5ae7b9ca 100644 --- a/jsonschemas/MessageKind11.jsonschema +++ b/jsonschemas/MessageKind11.jsonschema @@ -1,35 +1,56 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "ones": { - "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" + "$ref": "#/definitions/MessageKind11", + "definitions": { + "MessageKind11": { + "properties": { + "name": { + "type": "string" + }, + "ones": { + "items": { + "$ref": "#/definitions/samples.MessageKind1" }, - "complete": { - "type": "boolean" - } + "type": "array" + }, + "kind2": { + "$ref": "#/definitions/samples.MessageKind2", + "additionalProperties": true }, - "additionalProperties": true, - "type": "object" + "kind3": { + "$ref": "#/definitions/samples.MessageKind3", + "additionalProperties": true + }, + "kind4": { + "$ref": "#/definitions/samples.MessageKind4", + "additionalProperties": true + } }, - "type": "array" + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind1": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" }, - "kind2": { + "samples.MessageKind2": { "properties": { "name": { "type": "string" @@ -56,7 +77,7 @@ "additionalProperties": true, "type": "object" }, - "kind3": { + "samples.MessageKind3": { "properties": { "name": { "type": "string" @@ -80,7 +101,7 @@ "additionalProperties": true, "type": "object" }, - "kind4": { + "samples.MessageKind4": { "properties": { "name": { "type": "string" @@ -104,7 +125,5 @@ "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/MessageKind12.jsonschema b/jsonschemas/MessageKind12.jsonschema index d2c9222d..1ce79ada 100644 --- a/jsonschemas/MessageKind12.jsonschema +++ b/jsonschemas/MessageKind12.jsonschema @@ -1,119 +1,156 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" + "$ref": "#/definitions/MessageKind12", + "definitions": { + "MessageKind12": { + "properties": { + "name": { + "type": "string" + }, + "f": { + "$ref": "#/definitions/samples.MessageKind11", + "additionalProperties": true + }, + "kind5": { + "$ref": "#/definitions/samples.MessageKind5", + "additionalProperties": true + }, + "kind6": { + "$ref": "#/definitions/samples.MessageKind6", + "additionalProperties": true + }, + "kind7": { + "$ref": "#/definitions/samples.MessageKind7", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" }, - "f": { + "samples.MessageKind1": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind11": { "properties": { "name": { "type": "string" }, "ones": { "items": { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind1" }, "type": "array" }, "kind2": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "isa": { - "type": "boolean" - }, - "hasa": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind2", + "additionalProperties": true }, "kind3": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "someProp": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind3", + "additionalProperties": true }, "kind4": { - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "special": { - "type": "string" - } - }, - "additionalProperties": true, - "type": "object" + "$ref": "#/definitions/samples.MessageKind4", + "additionalProperties": true + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind2": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "isa": { + "type": "boolean" + }, + "hasa": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind3": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "someProp": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.MessageKind4": { + "properties": { + "name": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "special": { + "type": "string" } }, "additionalProperties": true, "type": "object" }, - "kind5": { + "samples.MessageKind5": { "properties": { "name": { "type": "string" @@ -137,7 +174,7 @@ "additionalProperties": true, "type": "object" }, - "kind6": { + "samples.MessageKind6": { "properties": { "name": { "type": "string" @@ -161,7 +198,7 @@ "additionalProperties": true, "type": "object" }, - "kind7": { + "samples.MessageKind7": { "properties": { "name": { "type": "string" @@ -185,7 +222,5 @@ "additionalProperties": true, "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/MessageWithComments.jsonschema b/jsonschemas/MessageWithComments.jsonschema index 60e1744c..3f3bfd1f 100644 --- a/jsonschemas/MessageWithComments.jsonschema +++ b/jsonschemas/MessageWithComments.jsonschema @@ -1,12 +1,17 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name1": { - "type": "string", - "description": "This field is supposed to represent blahblahblah" + "$ref": "#/definitions/MessageWithComments", + "definitions": { + "MessageWithComments": { + "properties": { + "name1": { + "type": "string", + "description": "This field is supposed to represent blahblahblah" + } + }, + "additionalProperties": true, + "type": "object", + "description": "This is a message level comment and talks about what this message is and why you should care about it!" } - }, - "additionalProperties": true, - "type": "object", - "description": "This is a message level comment and talks about what this message is and why you should care about it!" + } } \ No newline at end of file diff --git a/jsonschemas/NestedMessage.jsonschema b/jsonschemas/NestedMessage.jsonschema index 03724ba1..5cd21576 100644 --- a/jsonschemas/NestedMessage.jsonschema +++ b/jsonschemas/NestedMessage.jsonschema @@ -1,7 +1,21 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { + "$ref": "#/definitions/NestedMessage", + "definitions": { + "NestedMessage": { + "properties": { + "payload": { + "$ref": "#/definitions/samples.PayloadMessage", + "additionalProperties": false + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "samples.PayloadMessage": { "properties": { "name": { "type": "string" @@ -45,11 +59,6 @@ }, "additionalProperties": false, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": false, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/NestedObject.jsonschema b/jsonschemas/NestedObject.jsonschema index c17488de..9a1f2537 100644 --- a/jsonschemas/NestedObject.jsonschema +++ b/jsonschemas/NestedObject.jsonschema @@ -1,7 +1,21 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "payload": { + "$ref": "#/definitions/NestedObject", + "definitions": { + "NestedObject": { + "properties": { + "payload": { + "$ref": "#/definitions/samples.NestedObject.NestedPayload", + "additionalProperties": true + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.NestedObject.NestedPayload": { "properties": { "name": { "type": "string" @@ -45,11 +59,6 @@ }, "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/OneOf.jsonschema b/jsonschemas/OneOf.jsonschema index 41b0669a..cc7bae19 100644 --- a/jsonschemas/OneOf.jsonschema +++ b/jsonschemas/OneOf.jsonschema @@ -1,7 +1,37 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "bar": { + "$ref": "#/definitions/OneOf", + "definitions": { + "OneOf": { + "properties": { + "bar": { + "$ref": "#/definitions/samples.OneOf.Bar", + "additionalProperties": true + }, + "baz": { + "$ref": "#/definitions/samples.OneOf.Baz", + "additionalProperties": true + }, + "something": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object", + "oneOf": [ + { + "required": [ + "bar" + ] + }, + { + "required": [ + "baz" + ] + } + ] + }, + "samples.OneOf.Bar": { "properties": { "foo": { "type": "integer" @@ -10,7 +40,7 @@ "additionalProperties": true, "type": "object" }, - "baz": { + "samples.OneOf.Baz": { "properties": { "foo": { "type": "string" @@ -18,23 +48,6 @@ }, "additionalProperties": true, "type": "object" - }, - "something": { - "type": "boolean" - } - }, - "additionalProperties": true, - "type": "object", - "oneOf": [ - { - "required": [ - "bar" - ] - }, - { - "required": [ - "baz" - ] } - ] + } } \ No newline at end of file diff --git a/jsonschemas/PayloadMessage.jsonschema b/jsonschemas/PayloadMessage.jsonschema index bcc0a0fe..eba584f6 100644 --- a/jsonschemas/PayloadMessage.jsonschema +++ b/jsonschemas/PayloadMessage.jsonschema @@ -1,46 +1,51 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 - ], - "oneOf": [ - { + "$ref": "#/definitions/PayloadMessage", + "definitions": { + "PayloadMessage": { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/PayloadMessage2.jsonschema b/jsonschemas/PayloadMessage2.jsonschema index 1cb26ee8..90b433ec 100644 --- a/jsonschemas/PayloadMessage2.jsonschema +++ b/jsonschemas/PayloadMessage2.jsonschema @@ -1,54 +1,59 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "timestamp", - "id", - "rating", - "complete", - "topology" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 + "$ref": "#/definitions/PayloadMessage2", + "definitions": { + "PayloadMessage2": { + "required": [ + "name", + "timestamp", + "id", + "rating", + "complete", + "topology" ], - "oneOf": [ - { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Proto2NestedMessage.jsonschema b/jsonschemas/Proto2NestedMessage.jsonschema index 8de78e6a..0e11c17c 100644 --- a/jsonschemas/Proto2NestedMessage.jsonschema +++ b/jsonschemas/Proto2NestedMessage.jsonschema @@ -1,10 +1,24 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload" - ], - "properties": { - "payload": { + "$ref": "#/definitions/Proto2NestedMessage", + "definitions": { + "Proto2NestedMessage": { + "required": [ + "payload" + ], + "properties": { + "payload": { + "$ref": "#/definitions/samples.Proto2PayloadMessage", + "additionalProperties": false + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Proto2PayloadMessage": { "required": [ "name", "id" @@ -50,13 +64,8 @@ ] } }, - "additionalProperties": false, + "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Proto2NestedObject.jsonschema b/jsonschemas/Proto2NestedObject.jsonschema index d1404995..74bfb45f 100644 --- a/jsonschemas/Proto2NestedObject.jsonschema +++ b/jsonschemas/Proto2NestedObject.jsonschema @@ -1,11 +1,25 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "payload", - "description" - ], - "properties": { - "payload": { + "$ref": "#/definitions/Proto2NestedObject", + "definitions": { + "Proto2NestedObject": { + "required": [ + "payload", + "description" + ], + "properties": { + "payload": { + "$ref": "#/definitions/samples.Proto2NestedObject.NestedPayload", + "additionalProperties": false + }, + "description": { + "type": "string" + } + }, + "additionalProperties": true, + "type": "object" + }, + "samples.Proto2NestedObject.NestedPayload": { "required": [ "name", "timestamp", @@ -55,13 +69,8 @@ ] } }, - "additionalProperties": false, + "additionalProperties": true, "type": "object" - }, - "description": { - "type": "string" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Proto2PayloadMessage.jsonschema b/jsonschemas/Proto2PayloadMessage.jsonschema index be928fdf..643c8756 100644 --- a/jsonschemas/Proto2PayloadMessage.jsonschema +++ b/jsonschemas/Proto2PayloadMessage.jsonschema @@ -1,50 +1,55 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "name", - "id" - ], - "properties": { - "name": { - "type": "string" - }, - "timestamp": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "rating": { - "type": "number" - }, - "complete": { - "type": "boolean" - }, - "topology": { - "enum": [ - "FLAT", - 0, - "NESTED_OBJECT", - 1, - "NESTED_MESSAGE", - 2, - "ARRAY_OF_TYPE", - 3, - "ARRAY_OF_OBJECT", - 4, - "ARRAY_OF_MESSAGE", - 5 + "$ref": "#/definitions/Proto2PayloadMessage", + "definitions": { + "Proto2PayloadMessage": { + "required": [ + "name", + "id" ], - "oneOf": [ - { + "properties": { + "name": { "type": "string" }, - { + "timestamp": { + "type": "string" + }, + "id": { "type": "integer" + }, + "rating": { + "type": "number" + }, + "complete": { + "type": "boolean" + }, + "topology": { + "enum": [ + "FLAT", + 0, + "NESTED_OBJECT", + 1, + "NESTED_MESSAGE", + 2, + "ARRAY_OF_TYPE", + 3, + "ARRAY_OF_OBJECT", + 4, + "ARRAY_OF_MESSAGE", + 5 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] } - ] + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Proto2Required.jsonschema b/jsonschemas/Proto2Required.jsonschema index 8a79bf2b..568b5064 100644 --- a/jsonschemas/Proto2Required.jsonschema +++ b/jsonschemas/Proto2Required.jsonschema @@ -1,19 +1,24 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" + "$ref": "#/definitions/Proto2Required", + "definitions": { + "Proto2Required": { + "required": [ + "query" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Proto3Required.jsonschema b/jsonschemas/Proto3Required.jsonschema index 89e82910..2ac97ca4 100644 --- a/jsonschemas/Proto3Required.jsonschema +++ b/jsonschemas/Proto3Required.jsonschema @@ -1,20 +1,25 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "required": [ - "query", - "page_number" - ], - "properties": { - "query": { - "type": "string" - }, - "page_number": { - "type": "integer" - }, - "result_per_page": { - "type": "integer" + "$ref": "#/definitions/Proto3Required", + "definitions": { + "Proto3Required": { + "required": [ + "query", + "page_number" + ], + "properties": { + "query": { + "type": "string" + }, + "page_number": { + "type": "integer" + }, + "result_per_page": { + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/SecondMessage.jsonschema b/jsonschemas/SecondMessage.jsonschema index edbc1c86..200e7db9 100644 --- a/jsonschemas/SecondMessage.jsonschema +++ b/jsonschemas/SecondMessage.jsonschema @@ -1,22 +1,27 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "name2": { - "type": "string" - }, - "timestamp2": { - "type": "string" - }, - "id2": { - "type": "integer" - }, - "rating2": { - "type": "number" - }, - "complete2": { - "type": "boolean" + "$ref": "#/definitions/SecondMessage", + "definitions": { + "SecondMessage": { + "properties": { + "name2": { + "type": "string" + }, + "timestamp2": { + "type": "string" + }, + "id2": { + "type": "integer" + }, + "rating2": { + "type": "number" + }, + "complete2": { + "type": "boolean" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/Timestamp.jsonschema b/jsonschemas/Timestamp.jsonschema index a8d4b782..54c6acc5 100644 --- a/jsonschemas/Timestamp.jsonschema +++ b/jsonschemas/Timestamp.jsonschema @@ -1,11 +1,16 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "timestamp": { - "type": "string", - "format": "date-time" + "$ref": "#/definitions/Timestamp", + "definitions": { + "Timestamp": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": true, + "type": "object" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file diff --git a/jsonschemas/WellKnown.jsonschema b/jsonschemas/WellKnown.jsonschema index 940b4bbf..6f0b80f9 100644 --- a/jsonschemas/WellKnown.jsonschema +++ b/jsonschemas/WellKnown.jsonschema @@ -1,37 +1,42 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "string_value": { - "additionalProperties": true, - "type": "string" - }, - "map_of_integers": { - "additionalProperties": { - "additionalProperties": true, - "type": "integer" - }, - "type": "object" - }, - "map_of_scalar_integers": { - "additionalProperties": { - "type": "integer" + "$ref": "#/definitions/WellKnown", + "definitions": { + "WellKnown": { + "properties": { + "string_value": { + "additionalProperties": true, + "type": "string" + }, + "map_of_integers": { + "additionalProperties": { + "additionalProperties": true, + "type": "integer" + }, + "type": "object" + }, + "map_of_scalar_integers": { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + "list_of_integers": { + "items": { + "type": "integer", + "description": "Wrapper message for `int32`.\n\n The JSON representation for `Int32Value` is JSON number." + }, + "type": "array" + }, + "duration": { + "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)s$", + "type": "string", + "description": "This is a duration:", + "format": "regex" + } }, + "additionalProperties": true, "type": "object" - }, - "list_of_integers": { - "items": { - "type": "integer", - "description": "Wrapper message for `int32`.\n\n The JSON representation for `Int32Value` is JSON number." - }, - "type": "array" - }, - "duration": { - "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)s$", - "type": "string", - "description": "This is a duration:", - "format": "regex" } - }, - "additionalProperties": true, - "type": "object" + } } \ No newline at end of file