diff --git a/Makefile b/Makefile index 7878f088..eb0a140a 100644 --- a/Makefile +++ b/Makefile @@ -42,13 +42,17 @@ samples: build @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=disallow_bigints_as_strings:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/SeveralMessages.proto || echo "No messages found (SeveralMessages.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=disallow_bigints_as_strings:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/Timestamp.proto || echo "No messages found (Timestamp.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=all_fields_required:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/PayloadMessage2.proto || echo "No messages found (PayloadMessage2.proto)" - @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=json_fieldnames:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/JSONFields.proto || echo "No messages found (JSONFields.proto)" + @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=json_fieldnames:jsonschemas -I. --proto_path=${PROTO_PATH} ${PROTO_PATH}/JSONFields.proto || echo "No messages found (JSONFields.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/ArrayOfEnums.proto || echo "No messages found (SeveralMessages.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/Maps.proto || echo "No messages found (Maps.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/MessageWithComments.proto || echo "No messages found (MessageWithComments.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/Proto2Required.proto || echo "No messages found (Proto2Required.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/Proto2NestedMessage.proto || echo "No messages found (Proto2NestedMessage.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/GoogleValue.proto || echo "No messages found (GoogleValue.proto)" + @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/GoogleInt64Value.proto || echo "No messages found (GoogleInt64Value.proto)" + @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=disallow_bigints_as_strings:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/GoogleInt64ValueDisallowString.proto || echo "No messages found (GoogleInt64ValueDisallowString.proto)" + @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=allow_null_values:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/GoogleInt64ValueAllowNull.proto || echo "No messages found (GoogleInt64ValueAllowNull.proto)" + @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=disallow_bigints_as_strings,allow_null_values:jsonschemas --proto_path=${PROTO_PATH} ${PROTO_PATH}/GoogleInt64ValueDisallowStringAllowNull.proto || echo "No messages found (GoogleInt64ValueDisallowStringAllowNull.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas -I. --proto_path=${PROTO_PATH} ${PROTO_PATH}/OptionEnumsAsConstants.proto || echo "No messages found (OptionEnumsAsConstants.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas -I. --proto_path=${PROTO_PATH} ${PROTO_PATH}/OptionFileExtension.proto || echo "No messages found (OptionFileExtension.proto)" @protoc --plugin=bin/protoc-gen-jsonschema --jsonschema_out=jsonschemas -I. --proto_path=${PROTO_PATH} ${PROTO_PATH}/OptionIgnoredField.proto || echo "No messages found (HiddenFields.proto)" diff --git a/internal/converter/converter_test.go b/internal/converter/converter_test.go index 9f4f7fd5..10d18691 100644 --- a/internal/converter/converter_test.go +++ b/internal/converter/converter_test.go @@ -227,6 +227,40 @@ func configureSampleProtos() map[string]sampleProto { ObjectsToValidateFail: []string{testdata.GoogleValueFail}, ObjectsToValidatePass: []string{testdata.GoogleValuePass}, }, + "GoogleInt64Value": { + ExpectedJSONSchema: []string{testdata.GoogleInt64Value}, + FilesToGenerate: []string{"GoogleInt64Value.proto"}, + ProtoFileName: "GoogleInt64Value.proto", + ObjectsToValidateFail: []string{testdata.GoogleInt64ValueFail}, + ObjectsToValidatePass: []string{testdata.GoogleInt64ValuePass}, + }, + "GoogleInt64ValueAllowNull": { + Flags: ConverterFlags{AllowNullValues: true}, + ExpectedJSONSchema: []string{testdata.GoogleInt64ValueAllowNull}, + FilesToGenerate: []string{"GoogleInt64ValueAllowNull.proto"}, + ProtoFileName: "GoogleInt64ValueAllowNull.proto", + ObjectsToValidateFail: []string{testdata.GoogleInt64ValueAllowNullFail}, + ObjectsToValidatePass: []string{testdata.GoogleInt64ValueAllowNullPass}, + }, + "GoogleInt64ValueDisallowString": { + Flags: ConverterFlags{DisallowBigIntsAsStrings: true}, + ExpectedJSONSchema: []string{testdata.GoogleInt64ValueDisallowString}, + FilesToGenerate: []string{"GoogleInt64ValueDisallowString.proto"}, + ProtoFileName: "GoogleInt64ValueDisallowString.proto", + ObjectsToValidateFail: []string{testdata.GoogleInt64ValueDisallowStringFail}, + ObjectsToValidatePass: []string{testdata.GoogleInt64ValueDisallowStringPass}, + }, + "GoogleInt64ValueDisallowStringAllowNull": { + Flags: ConverterFlags{ + DisallowBigIntsAsStrings: true, + AllowNullValues: true, + }, + ExpectedJSONSchema: []string{testdata.GoogleInt64ValueDisallowStringAllowNull}, + FilesToGenerate: []string{"GoogleInt64ValueDisallowStringAllowNull.proto"}, + ProtoFileName: "GoogleInt64ValueDisallowStringAllowNull.proto", + ObjectsToValidateFail: []string{testdata.GoogleInt64ValueDisallowStringAllowNullFail}, + ObjectsToValidatePass: []string{testdata.GoogleInt64ValueDisallowStringAllowNullPass}, + }, "ImportedEnum": { ExpectedJSONSchema: []string{testdata.ImportedEnum}, FilesToGenerate: []string{"ImportedEnum.proto"}, diff --git a/internal/converter/testdata/google_int64_value.go b/internal/converter/testdata/google_int64_value.go new file mode 100644 index 00000000..5c566ec5 --- /dev/null +++ b/internal/converter/testdata/google_int64_value.go @@ -0,0 +1,23 @@ +package testdata + +const GoogleInt64Value = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64Value", + "definitions": { + "GoogleInt64Value": { + "properties": { + "big_number": { + "additionalProperties": true, + "type": "string" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Google Int 64 Value" + } + } +}` + +const GoogleInt64ValueFail = `{"big_number": 12345}` + +const GoogleInt64ValuePass = `{"big_number": "12345"}` diff --git a/internal/converter/testdata/google_int64_value_allow_null.go b/internal/converter/testdata/google_int64_value_allow_null.go new file mode 100644 index 00000000..f14ad639 --- /dev/null +++ b/internal/converter/testdata/google_int64_value_allow_null.go @@ -0,0 +1,38 @@ +package testdata + +const GoogleInt64ValueAllowNull = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueAllowNull", + "definitions": { + "GoogleInt64ValueAllowNull": { + "properties": { + "big_number": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "title": "Int 64 Value", + "description": "Wrapper message for ` + "`int64`" + `. The JSON representation for ` + "`Int64Value`" + ` is JSON string." + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Google Int 64 Value Allow Null" + } + } +}` + +const GoogleInt64ValueAllowNullFail = `{"big_number": 12345}` + +const GoogleInt64ValueAllowNullPass = `{"big_number": null}` diff --git a/internal/converter/testdata/google_int64_value_disallow_string.go b/internal/converter/testdata/google_int64_value_disallow_string.go new file mode 100644 index 00000000..fd6549fb --- /dev/null +++ b/internal/converter/testdata/google_int64_value_disallow_string.go @@ -0,0 +1,23 @@ +package testdata + +const GoogleInt64ValueDisallowString = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueDisallowString", + "definitions": { + "GoogleInt64ValueDisallowString": { + "properties": { + "big_number": { + "additionalProperties": true, + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Google Int 64 Value Disallow String" + } + } +}` + +const GoogleInt64ValueDisallowStringFail = `{"big_number": "12345"}` + +const GoogleInt64ValueDisallowStringPass = `{"big_number": 12345}` diff --git a/internal/converter/testdata/google_int64_value_disallow_string_allow_null.go b/internal/converter/testdata/google_int64_value_disallow_string_allow_null.go new file mode 100644 index 00000000..e73ee97b --- /dev/null +++ b/internal/converter/testdata/google_int64_value_disallow_string_allow_null.go @@ -0,0 +1,38 @@ +package testdata + +const GoogleInt64ValueDisallowStringAllowNull = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueDisallowStringAllowNull", + "definitions": { + "GoogleInt64ValueDisallowStringAllowNull": { + "properties": { + "big_number": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ], + "title": "Int 64 Value", + "description": "Wrapper message for ` + "`int64`" + `. The JSON representation for ` + "`Int64Value`" + ` is JSON string." + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Google Int 64 Value Disallow String Allow Null" + } + } +}` + +const GoogleInt64ValueDisallowStringAllowNullFail = `{"big_number": "12345"}` + +const GoogleInt64ValueDisallowStringAllowNullPass = `{"big_number": null}` diff --git a/internal/converter/testdata/proto/GoogleInt64Value.proto b/internal/converter/testdata/proto/GoogleInt64Value.proto new file mode 100644 index 00000000..5f37e367 --- /dev/null +++ b/internal/converter/testdata/proto/GoogleInt64Value.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/wrappers.proto"; + +message GoogleInt64Value { + google.protobuf.Int64Value big_number = 1; +} diff --git a/internal/converter/testdata/proto/GoogleInt64ValueAllowNull.proto b/internal/converter/testdata/proto/GoogleInt64ValueAllowNull.proto new file mode 100644 index 00000000..83ba8746 --- /dev/null +++ b/internal/converter/testdata/proto/GoogleInt64ValueAllowNull.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/wrappers.proto"; + +message GoogleInt64ValueAllowNull { + google.protobuf.Int64Value big_number = 1; +} diff --git a/internal/converter/testdata/proto/GoogleInt64ValueDisallowString.proto b/internal/converter/testdata/proto/GoogleInt64ValueDisallowString.proto new file mode 100644 index 00000000..069b12b0 --- /dev/null +++ b/internal/converter/testdata/proto/GoogleInt64ValueDisallowString.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/wrappers.proto"; + +message GoogleInt64ValueDisallowString { + google.protobuf.Int64Value big_number = 1; +} diff --git a/internal/converter/testdata/proto/GoogleInt64ValueDisallowStringAllowNull.proto b/internal/converter/testdata/proto/GoogleInt64ValueDisallowStringAllowNull.proto new file mode 100644 index 00000000..61e96f17 --- /dev/null +++ b/internal/converter/testdata/proto/GoogleInt64ValueDisallowStringAllowNull.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +package samples; + +import "google/protobuf/wrappers.proto"; + +message GoogleInt64ValueDisallowStringAllowNull { + google.protobuf.Int64Value big_number = 1; +} diff --git a/internal/converter/types.go b/internal/converter/types.go index c2ec30c6..c8a4b78d 100644 --- a/internal/converter/types.go +++ b/internal/converter/types.go @@ -504,8 +504,18 @@ func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msgDesc *d switch *msgDesc.Name { case "DoubleValue", "FloatValue": jsonSchemaType.Type = gojsonschema.TYPE_NUMBER - case "Int32Value", "UInt32Value", "Int64Value", "UInt64Value": + case "Int32Value", "UInt32Value": jsonSchemaType.Type = gojsonschema.TYPE_INTEGER + case "Int64Value", "UInt64Value": + // BigInt as ints + if messageFlags.DisallowBigIntsAsStrings { + jsonSchemaType.Type = gojsonschema.TYPE_INTEGER + } else { + + // BigInt as strings + jsonSchemaType.Type = gojsonschema.TYPE_STRING + } + case "BoolValue": jsonSchemaType.Type = gojsonschema.TYPE_BOOLEAN case "BytesValue", "StringValue": @@ -527,6 +537,8 @@ func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msgDesc *d // If we're allowing nulls then prepare a OneOf: if messageFlags.AllowNullValues { jsonSchemaType.OneOf = append(jsonSchemaType.OneOf, &jsonschema.Type{Type: gojsonschema.TYPE_NULL}, &jsonschema.Type{Type: jsonSchemaType.Type}) + // and clear the Type that was previously set. + jsonSchemaType.Type = "" return jsonSchemaType, nil } diff --git a/jsonschemas/GoogleInt64Value.json b/jsonschemas/GoogleInt64Value.json new file mode 100644 index 00000000..7d50fb1b --- /dev/null +++ b/jsonschemas/GoogleInt64Value.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64Value", + "definitions": { + "GoogleInt64Value": { + "properties": { + "big_number": { + "additionalProperties": true, + "type": "string" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Google Int 64 Value" + } + } +} \ No newline at end of file diff --git a/jsonschemas/GoogleInt64ValueAllowNull.json b/jsonschemas/GoogleInt64ValueAllowNull.json new file mode 100644 index 00000000..6797acce --- /dev/null +++ b/jsonschemas/GoogleInt64ValueAllowNull.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueAllowNull", + "definitions": { + "GoogleInt64ValueAllowNull": { + "properties": { + "big_number": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "title": "Int 64 Value", + "description": "Wrapper message for `int64`. The JSON representation for `Int64Value` is JSON string." + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Google Int 64 Value Allow Null" + } + } +} \ No newline at end of file diff --git a/jsonschemas/GoogleInt64ValueDisallowString.json b/jsonschemas/GoogleInt64ValueDisallowString.json new file mode 100644 index 00000000..404aa4e4 --- /dev/null +++ b/jsonschemas/GoogleInt64ValueDisallowString.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueDisallowString", + "definitions": { + "GoogleInt64ValueDisallowString": { + "properties": { + "big_number": { + "additionalProperties": true, + "type": "integer" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Google Int 64 Value Disallow String" + } + } +} \ No newline at end of file diff --git a/jsonschemas/GoogleInt64ValueDisallowStringAllowNull.json b/jsonschemas/GoogleInt64ValueDisallowStringAllowNull.json new file mode 100644 index 00000000..fa88cd00 --- /dev/null +++ b/jsonschemas/GoogleInt64ValueDisallowStringAllowNull.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/GoogleInt64ValueDisallowStringAllowNull", + "definitions": { + "GoogleInt64ValueDisallowStringAllowNull": { + "properties": { + "big_number": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ], + "title": "Int 64 Value", + "description": "Wrapper message for `int64`. The JSON representation for `Int64Value` is JSON string." + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Google Int 64 Value Disallow String Allow Null" + } + } +} \ No newline at end of file diff --git a/jsonschemas/JSONFields.json b/jsonschemas/JSONFields.json index d6393f97..79143a5e 100644 --- a/jsonschemas/JSONFields.json +++ b/jsonschemas/JSONFields.json @@ -3,6 +3,9 @@ "$ref": "#/definitions/JSONFields", "definitions": { "JSONFields": { + "required": [ + "otherNumb" + ], "properties": { "name": { "type": "string" @@ -21,10 +24,14 @@ }, "snakeNumb": { "type": "string" + }, + "otherNumb": { + "type": "integer" } }, "additionalProperties": true, - "type": "object" + "type": "object", + "title": "JSON Fields" } } } \ No newline at end of file