diff --git a/README.md b/README.md index 84a6eccd..c7a1abbc 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ protoc \ |`json_fieldnames`| Use JSON field names only | |`prefix_schema_files_with_package`| Prefix the output filename with package | |`proto_and_json_fieldnames`| Use proto and JSON field names | +|`type_names_with_no_package`| When generating type names and refs, do not include the full package in the type name | Custom Proto Options @@ -239,6 +240,16 @@ protoc \ --proto_path=internal/converter/testdata/proto internal/converter/testdata/proto/ArrayOfPrimitives.proto ``` +### Generate type names without fully qualified package + +By default, referenced type names will be generated using the fully qualified package and type name. e.g `packageName.TypeName`. +Setting this option will generate type names and their references only as `TypeName` + +```sh +protoc \ +--jsonschema_out=type_names_with_no_package:. \ +--proto_path=internal/converter/testdata/proto internal/converter/testdata/proto/ArrayOfPrimitives.proto +``` Sample protos (for testing) --------------------------- diff --git a/internal/converter/converter.go b/internal/converter/converter.go index d3fd05a7..04064d2f 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -59,6 +59,7 @@ type ConverterFlags struct { PrefixSchemaFilesWithPackage bool UseJSONFieldnamesOnly bool UseProtoAndJSONFieldNames bool + TypeNamesWithNoPackage bool } // New returns a configured *Converter (defaulting to draft-04 version): @@ -118,6 +119,8 @@ func (c *Converter) parseGeneratorParameters(parameters string) { c.Flags.PrefixSchemaFilesWithPackage = true case "proto_and_json_fieldnames": c.Flags.UseProtoAndJSONFieldNames = true + case "type_names_with_no_package": + c.Flags.TypeNamesWithNoPackage = true } // look for specific message targets diff --git a/internal/converter/converter_test.go b/internal/converter/converter_test.go index 5ad31c6b..02c9df4e 100644 --- a/internal/converter/converter_test.go +++ b/internal/converter/converter_test.go @@ -144,6 +144,14 @@ func configureSampleProtos() map[string]sampleProto { ObjectsToValidateFail: []string{testdata.PayloadMessageFail, testdata.ArrayOfMessagesFail}, ObjectsToValidatePass: []string{testdata.PayloadMessagePass, testdata.ArrayOfMessagesPass}, }, + "TypeNamesWithNoPackage": { + Flags: ConverterFlags{TypeNamesWithNoPackage: true}, + ExpectedJSONSchema: []string{testdata.PayloadMessage, testdata.TypeNamesWithNoPackage}, + FilesToGenerate: []string{"ArrayOfMessages.proto", "PayloadMessage.proto"}, + ProtoFileName: "ArrayOfMessages.proto", + ObjectsToValidateFail: []string{testdata.PayloadMessageFail, testdata.TypeNamesWithNoPackageFail}, + ObjectsToValidatePass: []string{testdata.PayloadMessagePass, testdata.TypeNamesWithNoPackagePass}, + }, "ArrayOfObjects": { Flags: ConverterFlags{AllowNullValues: true}, ExpectedJSONSchema: []string{testdata.ArrayOfObjects}, diff --git a/internal/converter/testdata/type_names_with_no_package.go b/internal/converter/testdata/type_names_with_no_package.go new file mode 100644 index 00000000..73dcdc15 --- /dev/null +++ b/internal/converter/testdata/type_names_with_no_package.go @@ -0,0 +1,85 @@ +package testdata + +const TypeNamesWithNoPackage = `{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ArrayOfMessages", + "definitions": { + "ArrayOfMessages": { + "properties": { + "description": { + "type": "string" + }, + "payload": { + "items": { + "$ref": "#/definitions/PayloadMessage" + }, + "type": "array" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Array Of Messages" + }, + "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" + } + ], + "title": "Topology" + } + }, + "additionalProperties": true, + "type": "object", + "title": "Payload Message" + } + } +}` + +const TypeNamesWithNoPackageFail = `{ + "description": "something", + "payload": [ + {"topology": "cruft"} + ] +}` + +const TypeNamesWithNoPackagePass = `{ + "description": "something", + "payload": [ + {"topology": "ARRAY_OF_MESSAGE"} + ] +}` diff --git a/internal/converter/types.go b/internal/converter/types.go index 0b137087..f4a63a72 100644 --- a/internal/converter/types.go +++ b/internal/converter/types.go @@ -405,14 +405,20 @@ func (c *Converter) convertMessageType(curPkg *ProtoPackage, msgDesc *descriptor // Build up a list of JSONSchema type definitions for every message: definitions := jsonschema.Definitions{} - for refmsgDesc, name := range duplicatedMessages { + for refmsgDesc, nameWithPackage := range duplicatedMessages { + var typeName string + if c.Flags.TypeNamesWithNoPackage { + typeName = refmsgDesc.GetName(); + } else { + typeName = nameWithPackage; + } refType, err := c.recursiveConvertMessageType(curPkg, refmsgDesc, "", duplicatedMessages, true) if err != nil { return nil, err } // Add the schema to our definitions: - definitions[name] = refType + definitions[typeName] = refType } // Put together a JSON schema with our discovered definitions, and a $ref for the root type: @@ -568,9 +574,15 @@ func (c *Converter) recursiveConvertMessageType(curPkg *ProtoPackage, msgDesc *d jsonSchemaType.Properties = orderedmap.New() // Look up references: - if refName, ok := duplicatedMessages[msgDesc]; ok && !ignoreDuplicatedMessages { + if nameWithPackage, ok := duplicatedMessages[msgDesc]; ok && !ignoreDuplicatedMessages { + var typeName string + if c.Flags.TypeNamesWithNoPackage { + typeName = msgDesc.GetName(); + } else { + typeName = nameWithPackage; + } return &jsonschema.Type{ - Ref: fmt.Sprintf("%s%s", c.refPrefix, refName), + Ref: fmt.Sprintf("%s%s", c.refPrefix, typeName), }, nil }