From e11bcaa43e54109493b5359eaa3829ad3486071c Mon Sep 17 00:00:00 2001 From: Alexander Staubo Date: Fri, 5 Oct 2018 16:28:02 -0400 Subject: [PATCH] Detect cyclical dependencies between types that reference each other. Better handling of enum declarations. --- pkg/codegen/utils.go | 18 ++ pkg/generator/generate.go | 124 ++++++------- pkg/generator/utils.go | 33 ++++ tests/data/core/4.2.1_array.go.output | 17 +- tests/data/core/object.go.output | 12 +- tests/data/core/objectEmpty.go.output | 5 +- tests/data/core/objectNested.go.output | 4 +- tests/data/core/primitives.go.output | 4 +- tests/data/core/ref.go.output | 3 +- tests/data/core/refExternalFile.go.output | 4 +- .../core/refExternalFileWithDupe.go.output | 5 +- tests/data/core/refToEnum.go.output | 42 +++++ tests/data/core/refToEnum.json | 16 ++ .../data/core/refToPrimitiveString.go.output | 10 + tests/data/core/refToPrimitiveString.json | 15 ++ tests/data/crossPackage/other.go.output | 2 +- tests/data/crossPackage/schema.go.output | 4 +- tests/data/misc/capitalization.go.output | 2 +- tests/data/miscWithDefaults/case.go.output | 2 +- .../data/miscWithDefaults/caseDupes.go.output | 2 +- tests/data/miscWithDefaults/cyclic.go.output | 18 ++ tests/data/miscWithDefaults/cyclic.json | 28 +++ .../cyclicAndRequired1.go.output | 39 ++++ .../miscWithDefaults/cyclicAndRequired1.json | 29 +++ .../cyclicAndRequired2.go.output | 57 ++++++ .../miscWithDefaults/cyclicAndRequired2.json | 30 +++ .../emptyDefinition.FAIL.json | 8 - .../rootEmptyJustDefinitions.go.output | 2 +- .../rootIsArrayOfString.go.output | 2 +- .../validation/10.1_description.go.output | 4 +- tests/data/validation/6.1.2_enum.go.output | 173 ++++++++++-------- .../validation/6.5.3_requiredFields.go.output | 56 +++--- tests/integration_test.go | 3 +- 33 files changed, 575 insertions(+), 198 deletions(-) create mode 100644 tests/data/core/refToEnum.go.output create mode 100644 tests/data/core/refToEnum.json create mode 100644 tests/data/core/refToPrimitiveString.go.output create mode 100644 tests/data/core/refToPrimitiveString.json create mode 100644 tests/data/miscWithDefaults/cyclic.go.output create mode 100644 tests/data/miscWithDefaults/cyclic.json create mode 100644 tests/data/miscWithDefaults/cyclicAndRequired1.go.output create mode 100644 tests/data/miscWithDefaults/cyclicAndRequired1.json create mode 100644 tests/data/miscWithDefaults/cyclicAndRequired2.go.output create mode 100644 tests/data/miscWithDefaults/cyclicAndRequired2.json delete mode 100644 tests/data/miscWithDefaults/emptyDefinition.FAIL.json diff --git a/pkg/codegen/utils.go b/pkg/codegen/utils.go index 1b07bd39..1f169af0 100644 --- a/pkg/codegen/utils.go +++ b/pkg/codegen/utils.go @@ -6,6 +6,24 @@ import ( "github.com/atombender/go-jsonschema/pkg/schemas" ) +func WrapTypeInPointer(t Type) Type { + if isPointerType(t) { + return t + } + return &PointerType{Type: t} +} + +func isPointerType(t Type) bool { + switch x := t.(type) { + case *PointerType: + return true + case *NamedType: + return isPointerType(x.Decl.Type) + default: + return false + } +} + func PrimitiveTypeFromJSONSchemaType(jsType string) (Type, error) { switch jsType { case schemas.TypeNameString: diff --git a/pkg/generator/generate.go b/pkg/generator/generate.go index 8b015c5c..397d5908 100644 --- a/pkg/generator/generate.go +++ b/pkg/generator/generate.go @@ -7,7 +7,6 @@ import ( "os" "path/filepath" "reflect" - "sort" "strings" "unicode" @@ -37,6 +36,8 @@ type Generator struct { emitter *codegen.Emitter outputs map[string]*output schemaCacheByFileName map[string]*schemas.Schema + inScope map[qualifiedDefinition]struct{} + warner func(string) } func New(config Config) (*Generator, error) { @@ -181,7 +182,7 @@ func (g *Generator) beginOutput( } output := &output{ - warner: g.config.Warner, + warner: g.warner, file: &codegen.File{ FileName: outputName, Package: pkg, @@ -286,6 +287,11 @@ func (g *schemaGenerator) generateReferencedType(ref string) (codegen.Type, erro schema = g.schema } + qual := qualifiedDefinition{ + schema: schema, + name: defName, + } + var def *schemas.Type if defName != "" { // TODO: Support nested definitions @@ -295,14 +301,24 @@ func (g *schemaGenerator) generateReferencedType(ref string) (codegen.Type, erro return nil, fmt.Errorf("definition %q (from ref %q) does not exist in schema", defName, ref) } if def.Type == "" && len(def.Properties) == 0 { - return nil, nil + return &codegen.EmptyInterfaceType{}, nil } - // Minor hack to make definitions default to being objects - def.Type = schemas.TypeNameObject defName = g.identifierize(defName) } else { def = schema.Type defName = g.getRootTypeName(schema, fileName) + if def.Type == "" { + // Minor hack to make definitions default to being objects + def.Type = schemas.TypeNameObject + } + } + + _, isCycle := g.inScope[qual] + if !isCycle { + g.inScope[qual] = struct{}{} + defer func() { + delete(g.inScope, qual) + }() } var sg *schemaGenerator @@ -327,6 +343,13 @@ func (g *schemaGenerator) generateReferencedType(ref string) (codegen.Type, erro return nil, err } + nt := t.(*codegen.NamedType) + + if isCycle { + g.warner(fmt.Sprintf("Cycle detected; must wrap type %s in pointer", nt.Decl.Name)) + t = codegen.WrapTypeInPointer(t) + } + if sg.output.file.Package.QualifiedName == g.output.file.Package.QualifiedName { return t, nil } @@ -344,31 +367,39 @@ func (g *schemaGenerator) generateReferencedType(ref string) (codegen.Type, erro return &codegen.NamedType{ Package: &sg.output.file.Package, - Decl: t.(*codegen.NamedType).Decl, + Decl: nt.Decl, }, nil } func (g *schemaGenerator) generateDeclaredType( t *schemas.Type, scope nameScope) (codegen.Type, error) { - if t, ok := g.output.declsBySchema[t]; ok { - return &codegen.NamedType{Decl: t}, nil + if decl, ok := g.output.declsBySchema[t]; ok { + return &codegen.NamedType{Decl: decl}, nil + } + + if t.Enum != nil { + return g.generateEnumType(t, scope) } decl := codegen.TypeDecl{ Name: g.output.uniqueTypeName(scope.string()), Comment: t.Description, } + g.output.declsBySchema[t] = &decl + g.output.declsByName[decl.Name] = &decl + theType, err := g.generateType(t, scope) if err != nil { return nil, err } - if d, ok := theType.(*codegen.NamedType); ok { - return d, nil + if isNamedType(theType) { + // Don't declare named types under a new name + delete(g.output.declsBySchema, t) + delete(g.output.declsByName, decl.Name) + return theType, nil } decl.Type = theType - g.output.declsBySchema[t] = &decl - g.output.declsByName[decl.Name] = &decl g.output.file.Package.AddDecl(&decl) if structType, ok := theType.(*codegen.StructType); ok { @@ -441,28 +472,9 @@ func (g *schemaGenerator) generateType( if t.Items == nil { return nil, errors.New("array property must have 'items' set to a type") } - - var elemType codegen.Type - if schemas.IsPrimitiveType(t.Items.Type) { - var err error - elemType, err = codegen.PrimitiveTypeFromJSONSchemaType(t.Items.Type) - if err != nil { - return nil, fmt.Errorf("cannot determine type of field: %s", err) - } - } else if t.Items.Type != "" { - var err error - elemType, err = g.generateDeclaredType(t.Items, scope.add("Elem")) - if err != nil { - return nil, err - } - } else if t.Items.Ref != "" { - var err error - elemType, err = g.generateReferencedType(t.Items.Ref) - if err != nil { - return nil, err - } - } else { - return nil, errors.New("array property must have a type") + elemType, err := g.generateType(t.Items, scope.add("Elem")) + if err != nil { + return nil, err } return codegen.ArrayType{elemType}, nil case schemas.TypeNameObject: @@ -474,7 +486,10 @@ func (g *schemaGenerator) generateType( if t.Ref != "" { return g.generateReferencedType(t.Ref) } - return codegen.PrimitiveTypeFromJSONSchemaType(t.Type) + if t.Type != "" { + return codegen.PrimitiveTypeFromJSONSchemaType(t.Type) + } + return codegen.EmptyInterfaceType{}, nil } func (g *schemaGenerator) generateStructType( @@ -482,7 +497,7 @@ func (g *schemaGenerator) generateStructType( scope nameScope) (codegen.Type, error) { if len(t.Properties) == 0 { if len(t.Required) > 0 { - g.config.Warner("object type with no properties has required fields; " + + g.warner("Object type with no properties has required fields; " + "skipping validation code for them since we don't know their types") } return &codegen.MapType{ @@ -507,7 +522,7 @@ func (g *schemaGenerator) generateStructType( if count, ok := uniqueNames[fieldName]; ok { uniqueNames[fieldName] = count + 1 fieldName = fmt.Sprintf("%s_%d", fieldName, count+1) - g.config.Warner(fmt.Sprintf("field %q maps to a field by the same name declared "+ + g.warner(fmt.Sprintf("field %q maps to a field by the same name declared "+ "in the same struct; it will be declared as %s", name, fieldName)) } else { uniqueNames[fieldName] = 1 @@ -542,7 +557,9 @@ func (g *schemaGenerator) generateStructType( structType.RequiredJSONFields = append(structType.RequiredJSONFields, structField.JSONName) } else { // Optional, so must be pointer - structField.Type = codegen.PointerType{Type: structField.Type} + if !structField.Type.IsNillable() { + structField.Type = codegen.WrapTypeInPointer(structField.Type) + } } structType.AddField(structField) @@ -617,7 +634,7 @@ func (g *schemaGenerator) generateEnumType( enumType = codegen.PrimitiveType{primitiveType} } if wrapInStruct { - g.config.Warner("Enum field wrapped in struct in order to store values of multiple types") + g.warner("Enum field wrapped in struct in order to store values of multiple types") enumType = &codegen.StructType{ Fields: []codegen.StructField{ { @@ -628,12 +645,8 @@ func (g *schemaGenerator) generateEnumType( } } - if enumDecl, ok := enumType.(*codegen.NamedType); ok { - return enumDecl, nil - } - enumDecl := codegen.TypeDecl{ - Name: g.output.uniqueTypeName(scope.add("Enum").string()), + Name: g.output.uniqueTypeName(scope.string()), Type: enumType, } g.output.file.Package.AddDecl(&enumDecl) @@ -749,6 +762,11 @@ type cachedEnum struct { enum *codegen.TypeDecl } +type qualifiedDefinition struct { + schema *schemas.Schema + name string +} + type nameScope []string func newNameScope(s string) nameScope { @@ -770,21 +788,3 @@ var ( varNamePlainStruct = "plain" varNameRawMap = "raw" ) - -func sortPropertiesByName(props map[string]*schemas.Type) []string { - names := make([]string, 0, len(props)) - for name := range props { - names = append(names, name) - } - sort.Strings(names) - return names -} - -func sortDefinitionsByName(defs schemas.Definitions) []string { - names := make([]string, 0, len(defs)) - for name := range defs { - names = append(names, name) - } - sort.Strings(names) - return names -} diff --git a/pkg/generator/utils.go b/pkg/generator/utils.go index 12a0d88e..a296badf 100644 --- a/pkg/generator/utils.go +++ b/pkg/generator/utils.go @@ -5,6 +5,9 @@ import ( "fmt" "sort" "unicode" + + "github.com/atombender/go-jsonschema/pkg/codegen" + "github.com/atombender/go-jsonschema/pkg/schemas" ) func hashArrayOfValues(values []interface{}) string { @@ -67,3 +70,33 @@ func splitIdentifierByCaseAndSeparators(s string) []string { } return result } + +func sortPropertiesByName(props map[string]*schemas.Type) []string { + names := make([]string, 0, len(props)) + for name := range props { + names = append(names, name) + } + sort.Strings(names) + return names +} + +func sortDefinitionsByName(defs schemas.Definitions) []string { + names := make([]string, 0, len(defs)) + for name := range defs { + names = append(names, name) + } + sort.Strings(names) + return names +} + +func isNamedType(t codegen.Type) bool { + switch x := t.(type) { + case *codegen.NamedType: + return true + case *codegen.PointerType: + if _, ok := x.Type.(*codegen.NamedType); ok { + return true + } + } + return false +} diff --git a/tests/data/core/4.2.1_array.go.output b/tests/data/core/4.2.1_array.go.output index 6edee970..6eebf15d 100644 --- a/tests/data/core/4.2.1_array.go.output +++ b/tests/data/core/4.2.1_array.go.output @@ -2,20 +2,21 @@ package test -type 421ArrayMyObjectArrayElem map[string]interface{} -type 421Array struct { +type A421ArrayMyObjectArrayElem map[string]interface{} + +type A421Array struct { // MyBooleanArray corresponds to the JSON schema field "myBooleanArray". - MyBooleanArray *[]bool `json:"myBooleanArray,omitempty"` + MyBooleanArray []bool `json:"myBooleanArray,omitempty"` // MyNullArray corresponds to the JSON schema field "myNullArray". - MyNullArray *[]interface{} `json:"myNullArray,omitempty"` + MyNullArray []interface{} `json:"myNullArray,omitempty"` // MyNumberArray corresponds to the JSON schema field "myNumberArray". - MyNumberArray *[]float64 `json:"myNumberArray,omitempty"` + MyNumberArray []float64 `json:"myNumberArray,omitempty"` // MyObjectArray corresponds to the JSON schema field "myObjectArray". - MyObjectArray *[]421ArrayMyObjectArrayElem `json:"myObjectArray,omitempty"` + MyObjectArray []A421ArrayMyObjectArrayElem `json:"myObjectArray,omitempty"` // MyStringArray corresponds to the JSON schema field "myStringArray". - MyStringArray *[]string `json:"myStringArray,omitempty"` -} \ No newline at end of file + MyStringArray []string `json:"myStringArray,omitempty"` +} diff --git a/tests/data/core/object.go.output b/tests/data/core/object.go.output index 0d245020..cc2236ed 100644 --- a/tests/data/core/object.go.output +++ b/tests/data/core/object.go.output @@ -1,6 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. package test + import "fmt" import "encoding/json" @@ -12,19 +13,22 @@ type ObjectMyObject struct { // UnmarshalJSON implements json.Unmarshaler. func (j *ObjectMyObject) UnmarshalJSON(b []byte) error { var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { return err } + if err := json.Unmarshal(b, &raw); err != nil { + return err + } if v, ok := raw["myString"]; !ok || v == nil { return fmt.Errorf("field myString: required") } type Plain ObjectMyObject var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { return err } + if err := json.Unmarshal(b, &plain); err != nil { + return err + } *j = ObjectMyObject(plain) return nil } - type Object struct { // MyObject corresponds to the JSON schema field "myObject". MyObject *ObjectMyObject `json:"myObject,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/objectEmpty.go.output b/tests/data/core/objectEmpty.go.output index 076eca34..3f85e525 100644 --- a/tests/data/core/objectEmpty.go.output +++ b/tests/data/core/objectEmpty.go.output @@ -3,7 +3,8 @@ package test type ObjectEmptyFoo map[string]interface{} + type ObjectEmpty struct { // Foo corresponds to the JSON schema field "foo". - Foo *ObjectEmptyFoo `json:"foo,omitempty"` -} \ No newline at end of file + Foo ObjectEmptyFoo `json:"foo,omitempty"` +} diff --git a/tests/data/core/objectNested.go.output b/tests/data/core/objectNested.go.output index 85a7780d..b33a19c4 100644 --- a/tests/data/core/objectNested.go.output +++ b/tests/data/core/objectNested.go.output @@ -6,11 +6,13 @@ type ObjectNestedMyObjectMyObject struct { // MyString corresponds to the JSON schema field "myString". MyString *string `json:"myString,omitempty"` } + type ObjectNestedMyObject struct { // MyObject corresponds to the JSON schema field "myObject". MyObject *ObjectNestedMyObjectMyObject `json:"myObject,omitempty"` } + type ObjectNested struct { // MyObject corresponds to the JSON schema field "myObject". MyObject *ObjectNestedMyObject `json:"myObject,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/primitives.go.output b/tests/data/core/primitives.go.output index c3e70a12..66a275e1 100644 --- a/tests/data/core/primitives.go.output +++ b/tests/data/core/primitives.go.output @@ -7,11 +7,11 @@ type Primitives struct { MyBoolean *bool `json:"myBoolean,omitempty"` // MyNull corresponds to the JSON schema field "myNull". - MyNull *interface{} `json:"myNull,omitempty"` + MyNull interface{} `json:"myNull,omitempty"` // MyNumber corresponds to the JSON schema field "myNumber". MyNumber *float64 `json:"myNumber,omitempty"` // MyString corresponds to the JSON schema field "myString". MyString *string `json:"myString,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/ref.go.output b/tests/data/core/ref.go.output index b49c5ab5..f65341f0 100644 --- a/tests/data/core/ref.go.output +++ b/tests/data/core/ref.go.output @@ -6,10 +6,11 @@ type Thing struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty"` } + type Ref struct { // MyThing corresponds to the JSON schema field "myThing". MyThing *Thing `json:"myThing,omitempty"` // MyThing2 corresponds to the JSON schema field "myThing2". MyThing2 *Thing `json:"myThing2,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/refExternalFile.go.output b/tests/data/core/refExternalFile.go.output index c55bad5e..6d6873ca 100644 --- a/tests/data/core/refExternalFile.go.output +++ b/tests/data/core/refExternalFile.go.output @@ -6,6 +6,7 @@ type Thing struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty"` } + type Ref struct { // MyThing corresponds to the JSON schema field "myThing". MyThing *Thing `json:"myThing,omitempty"` @@ -13,6 +14,7 @@ type Ref struct { // MyThing2 corresponds to the JSON schema field "myThing2". MyThing2 *Thing `json:"myThing2,omitempty"` } + type RefExternalFile struct { // MyExternalThing corresponds to the JSON schema field "myExternalThing". MyExternalThing *Thing `json:"myExternalThing,omitempty"` @@ -20,4 +22,4 @@ type RefExternalFile struct { // SomeOtherExternalThing corresponds to the JSON schema field // "someOtherExternalThing". SomeOtherExternalThing *Thing `json:"someOtherExternalThing,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/refExternalFileWithDupe.go.output b/tests/data/core/refExternalFileWithDupe.go.output index 1260e1ac..29896910 100644 --- a/tests/data/core/refExternalFileWithDupe.go.output +++ b/tests/data/core/refExternalFileWithDupe.go.output @@ -6,6 +6,7 @@ type Thing struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty"` } + type Ref struct { // MyThing corresponds to the JSON schema field "myThing". MyThing *Thing `json:"myThing,omitempty"` @@ -13,14 +14,16 @@ type Ref struct { // MyThing2 corresponds to the JSON schema field "myThing2". MyThing2 *Thing `json:"myThing2,omitempty"` } + type Thing_1 struct { // Something corresponds to the JSON schema field "something". Something *string `json:"something,omitempty"` } + type RefExternalFileWithDupe struct { // MyExternalThing corresponds to the JSON schema field "myExternalThing". MyExternalThing *Thing `json:"myExternalThing,omitempty"` // MyThing corresponds to the JSON schema field "myThing". MyThing *Thing_1 `json:"myThing,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/core/refToEnum.go.output b/tests/data/core/refToEnum.go.output new file mode 100644 index 00000000..2f3867bc --- /dev/null +++ b/tests/data/core/refToEnum.go.output @@ -0,0 +1,42 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package test + +import "fmt" +import "reflect" +import "encoding/json" + +type Thing string + +var enumValues_Thing = []interface{}{ + "x", + "y", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Thing) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_Thing { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_Thing, v) + } + *j = Thing(v) + return nil +} + +const ThingX Thing = "x" +const ThingY Thing = "y" + +type RefToEnum struct { + // MyThing corresponds to the JSON schema field "myThing". + MyThing *Thing `json:"myThing,omitempty"` +} diff --git a/tests/data/core/refToEnum.json b/tests/data/core/refToEnum.json new file mode 100644 index 00000000..d8bcd043 --- /dev/null +++ b/tests/data/core/refToEnum.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "https://example.com/refToPrimitive", + "type": "object", + "properties": { + "myThing": { + "$ref": "#/definitions/Thing" + } + }, + "definitions": { + "Thing": { + "type": "string", + "enum": ["x", "y"] + } + } +} diff --git a/tests/data/core/refToPrimitiveString.go.output b/tests/data/core/refToPrimitiveString.go.output new file mode 100644 index 00000000..1c385ab2 --- /dev/null +++ b/tests/data/core/refToPrimitiveString.go.output @@ -0,0 +1,10 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package test + +type Thing string + +type RefToPrimitiveString struct { + // MyThing corresponds to the JSON schema field "myThing". + MyThing *Thing `json:"myThing,omitempty"` +} diff --git a/tests/data/core/refToPrimitiveString.json b/tests/data/core/refToPrimitiveString.json new file mode 100644 index 00000000..e6a68b17 --- /dev/null +++ b/tests/data/core/refToPrimitiveString.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "https://example.com/refToPrimitive", + "type": "object", + "properties": { + "myThing": { + "$ref": "#/definitions/Thing" + } + }, + "definitions": { + "Thing": { + "type": "string" + } + } +} diff --git a/tests/data/crossPackage/other.go.output b/tests/data/crossPackage/other.go.output index 2525006e..a812dadd 100644 --- a/tests/data/crossPackage/other.go.output +++ b/tests/data/crossPackage/other.go.output @@ -5,4 +5,4 @@ package other type Thing struct { // S corresponds to the JSON schema field "s". S *string `json:"s,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/crossPackage/schema.go.output b/tests/data/crossPackage/schema.go.output index ed937457..72df6755 100644 --- a/tests/data/crossPackage/schema.go.output +++ b/tests/data/crossPackage/schema.go.output @@ -1,16 +1,18 @@ // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. package schema + import other "github.com/example/other" type Thing struct { // S corresponds to the JSON schema field "s". S *string `json:"s,omitempty"` } + type Schema struct { // DefInOtherSchema corresponds to the JSON schema field "defInOtherSchema". DefInOtherSchema *other.Thing `json:"defInOtherSchema,omitempty"` // DefInSameSchema corresponds to the JSON schema field "defInSameSchema". DefInSameSchema *Thing `json:"defInSameSchema,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/misc/capitalization.go.output b/tests/data/misc/capitalization.go.output index a1b14a52..f8d80b51 100644 --- a/tests/data/misc/capitalization.go.output +++ b/tests/data/misc/capitalization.go.output @@ -38,4 +38,4 @@ type Capitalization struct { // URLSomething corresponds to the JSON schema field "url_something". URLSomething *string `json:"url_something,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/miscWithDefaults/case.go.output b/tests/data/miscWithDefaults/case.go.output index ce79dad0..5447da67 100644 --- a/tests/data/miscWithDefaults/case.go.output +++ b/tests/data/miscWithDefaults/case.go.output @@ -20,4 +20,4 @@ type Case struct { // SnakeCase corresponds to the JSON schema field "snake_case". SnakeCase *string `json:"snake_case,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/miscWithDefaults/caseDupes.go.output b/tests/data/miscWithDefaults/caseDupes.go.output index 36c9b213..27afbca2 100644 --- a/tests/data/miscWithDefaults/caseDupes.go.output +++ b/tests/data/miscWithDefaults/caseDupes.go.output @@ -17,4 +17,4 @@ type CaseDupes struct { // Somefield corresponds to the JSON schema field "somefield". Somefield *string `json:"somefield,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/miscWithDefaults/cyclic.go.output b/tests/data/miscWithDefaults/cyclic.go.output new file mode 100644 index 00000000..8b2e4d8e --- /dev/null +++ b/tests/data/miscWithDefaults/cyclic.go.output @@ -0,0 +1,18 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package test + +type Bar struct { + // RefToFoo corresponds to the JSON schema field "refToFoo". + RefToFoo *Foo `json:"refToFoo,omitempty"` +} + +type Foo struct { + // RefToBar corresponds to the JSON schema field "refToBar". + RefToBar *Bar `json:"refToBar,omitempty"` +} + +type Cyclic struct { + // A corresponds to the JSON schema field "a". + A *Foo `json:"a,omitempty"` +} diff --git a/tests/data/miscWithDefaults/cyclic.json b/tests/data/miscWithDefaults/cyclic.json new file mode 100644 index 00000000..7f38e0f6 --- /dev/null +++ b/tests/data/miscWithDefaults/cyclic.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "https://example.com/cyclic", + "type": "object", + "properties": { + "a": { + "$ref": "#/definitions/Foo" + } + }, + "definitions": { + "Foo": { + "type": "object", + "properties": { + "refToBar": { + "$ref": "#/definitions/Bar" + } + } + }, + "Bar": { + "type": "object", + "properties": { + "refToFoo": { + "$ref": "#/definitions/Foo" + } + } + } + } +} diff --git a/tests/data/miscWithDefaults/cyclicAndRequired1.go.output b/tests/data/miscWithDefaults/cyclicAndRequired1.go.output new file mode 100644 index 00000000..437d5408 --- /dev/null +++ b/tests/data/miscWithDefaults/cyclicAndRequired1.go.output @@ -0,0 +1,39 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package test + +import "fmt" +import "encoding/json" + +type Bar struct { + // RefToFoo corresponds to the JSON schema field "refToFoo". + RefToFoo *Foo `json:"refToFoo,omitempty"` +} + +type Foo struct { + // RefToBar corresponds to the JSON schema field "refToBar". + RefToBar Bar `json:"refToBar"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Foo) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if v, ok := raw["refToBar"]; !ok || v == nil { + return fmt.Errorf("field refToBar: required") + } + type Plain Foo + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Foo(plain) + return nil +} + +type CyclicAndRequired1 struct { + // A corresponds to the JSON schema field "a". + A *Foo `json:"a,omitempty"` +} diff --git a/tests/data/miscWithDefaults/cyclicAndRequired1.json b/tests/data/miscWithDefaults/cyclicAndRequired1.json new file mode 100644 index 00000000..25d12e57 --- /dev/null +++ b/tests/data/miscWithDefaults/cyclicAndRequired1.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "https://example.com/cyclicAndRequired1", + "type": "object", + "properties": { + "a": { + "$ref": "#/definitions/Foo" + } + }, + "definitions": { + "Foo": { + "type": "object", + "required": ["refToBar"], + "properties": { + "refToBar": { + "$ref": "#/definitions/Bar" + } + } + }, + "Bar": { + "type": "object", + "properties": { + "refToFoo": { + "$ref": "#/definitions/Foo" + } + } + } + } +} diff --git a/tests/data/miscWithDefaults/cyclicAndRequired2.go.output b/tests/data/miscWithDefaults/cyclicAndRequired2.go.output new file mode 100644 index 00000000..c8fe5a4a --- /dev/null +++ b/tests/data/miscWithDefaults/cyclicAndRequired2.go.output @@ -0,0 +1,57 @@ +// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. + +package test + +import "fmt" +import "encoding/json" + +type Bar struct { + // RefToFoo corresponds to the JSON schema field "refToFoo". + RefToFoo *Foo `json:"refToFoo"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Bar) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if v, ok := raw["refToFoo"]; !ok || v == nil { + return fmt.Errorf("field refToFoo: required") + } + type Plain Bar + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Bar(plain) + return nil +} + +type Foo struct { + // RefToBar corresponds to the JSON schema field "refToBar". + RefToBar Bar `json:"refToBar"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Foo) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if v, ok := raw["refToBar"]; !ok || v == nil { + return fmt.Errorf("field refToBar: required") + } + type Plain Foo + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Foo(plain) + return nil +} + +type CyclicAndRequired2 struct { + // A corresponds to the JSON schema field "a". + A *Foo `json:"a,omitempty"` +} diff --git a/tests/data/miscWithDefaults/cyclicAndRequired2.json b/tests/data/miscWithDefaults/cyclicAndRequired2.json new file mode 100644 index 00000000..3198dbc4 --- /dev/null +++ b/tests/data/miscWithDefaults/cyclicAndRequired2.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "https://example.com/cyclicAndRequired2", + "type": "object", + "properties": { + "a": { + "$ref": "#/definitions/Foo" + } + }, + "definitions": { + "Foo": { + "type": "object", + "required": ["refToBar"], + "properties": { + "refToBar": { + "$ref": "#/definitions/Bar" + } + } + }, + "Bar": { + "type": "object", + "required": ["refToFoo"], + "properties": { + "refToFoo": { + "$ref": "#/definitions/Foo" + } + } + } + } +} diff --git a/tests/data/miscWithDefaults/emptyDefinition.FAIL.json b/tests/data/miscWithDefaults/emptyDefinition.FAIL.json deleted file mode 100644 index 4eac61bf..00000000 --- a/tests/data/miscWithDefaults/emptyDefinition.FAIL.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "https://example.com/empty_def", - "type": "object", - "properties": { - "foo": {} - } -} diff --git a/tests/data/miscWithDefaults/rootEmptyJustDefinitions.go.output b/tests/data/miscWithDefaults/rootEmptyJustDefinitions.go.output index 1da07b3c..f9214646 100644 --- a/tests/data/miscWithDefaults/rootEmptyJustDefinitions.go.output +++ b/tests/data/miscWithDefaults/rootEmptyJustDefinitions.go.output @@ -5,4 +5,4 @@ package test type Thing struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/miscWithDefaults/rootIsArrayOfString.go.output b/tests/data/miscWithDefaults/rootIsArrayOfString.go.output index ec0d2975..94a3ad6f 100644 --- a/tests/data/miscWithDefaults/rootIsArrayOfString.go.output +++ b/tests/data/miscWithDefaults/rootIsArrayOfString.go.output @@ -2,4 +2,4 @@ package test -type RootIsArrayOfString []string \ No newline at end of file +type RootIsArrayOfString []string diff --git a/tests/data/validation/10.1_description.go.output b/tests/data/validation/10.1_description.go.output index 2532956d..5fc20f01 100644 --- a/tests/data/validation/10.1_description.go.output +++ b/tests/data/validation/10.1_description.go.output @@ -3,11 +3,11 @@ package test // A simple schema. -type 101Description struct { +type A101Description struct { // MyDescriptionlessField corresponds to the JSON schema field // "myDescriptionlessField". MyDescriptionlessField *string `json:"myDescriptionlessField,omitempty"` // A string field. MyField *string `json:"myField,omitempty"` -} \ No newline at end of file +} diff --git a/tests/data/validation/6.1.2_enum.go.output b/tests/data/validation/6.1.2_enum.go.output index edbf831c..e15efda2 100644 --- a/tests/data/validation/6.1.2_enum.go.output +++ b/tests/data/validation/6.1.2_enum.go.output @@ -1,174 +1,197 @@ // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. package test + import "fmt" import "reflect" import "encoding/json" -type 612EnumMyBooleanTypedEnumEnum bool -var enumValues_612EnumMyBooleanTypedEnumEnum = []interface {}{ - true, - false, +type A612EnumMyBooleanTypedEnum bool + +var enumValues_A612EnumMyBooleanTypedEnum = []interface{}{ + true, + false, } // UnmarshalJSON implements json.Unmarshaler. -func (j *612EnumMyBooleanTypedEnumEnum) UnmarshalJSON(b []byte) error { +func (j *A612EnumMyBooleanTypedEnum) UnmarshalJSON(b []byte) error { var v bool - if err := json.Unmarshal(b, &v); err != nil { return err } + if err := json.Unmarshal(b, &v); err != nil { + return err + } var ok bool - for _, expected := range enumValues_612EnumMyBooleanTypedEnumEnum { - if reflect.DeepEqual(v, expected) { ok = true; break } + for _, expected := range enumValues_A612EnumMyBooleanTypedEnum { + if reflect.DeepEqual(v, expected) { + ok = true + break + } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_612EnumMyBooleanTypedEnumEnum, v) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_A612EnumMyBooleanTypedEnum, v) } - *j = 612EnumMyBooleanTypedEnumEnum(v) + *j = A612EnumMyBooleanTypedEnum(v) return nil } - -type 612EnumMyMixedUntypedEnumEnum struct { +type A612EnumMyMixedUntypedEnum struct { Value interface{} } -var enumValues_612EnumMyMixedUntypedEnumEnum = []interface {}{ - "red", - 1, - true, - nil, + +var enumValues_A612EnumMyMixedUntypedEnum = []interface{}{ + "red", + 1, + true, + nil, } // MarshalJSON implements json.Marshaler. -func (j *612EnumMyMixedUntypedEnumEnum) MarshalJSON() ([]byte, error) { +func (j *A612EnumMyMixedUntypedEnum) MarshalJSON() ([]byte, error) { return json.Marshal(j.Value) } - - // UnmarshalJSON implements json.Unmarshaler. -func (j *612EnumMyMixedUntypedEnumEnum) UnmarshalJSON(b []byte) error { +func (j *A612EnumMyMixedUntypedEnum) UnmarshalJSON(b []byte) error { var v struct { Value interface{} } - if err := json.Unmarshal(b, &v.Value); err != nil { return err } + if err := json.Unmarshal(b, &v.Value); err != nil { + return err + } var ok bool - for _, expected := range enumValues_612EnumMyMixedUntypedEnumEnum { - if reflect.DeepEqual(v.Value, expected) { ok = true; break } + for _, expected := range enumValues_A612EnumMyMixedUntypedEnum { + if reflect.DeepEqual(v.Value, expected) { + ok = true + break + } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_612EnumMyMixedUntypedEnumEnum, v.Value) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_A612EnumMyMixedUntypedEnum, v.Value) } - *j = 612EnumMyMixedUntypedEnumEnum(v) + *j = A612EnumMyMixedUntypedEnum(v) return nil } - -type 612EnumMyNullTypedEnumEnum struct { +type A612EnumMyNullTypedEnum struct { Value interface{} } -var enumValues_612EnumMyNullTypedEnumEnum = []interface {}{ - nil, + +var enumValues_A612EnumMyNullTypedEnum = []interface{}{ + nil, } // MarshalJSON implements json.Marshaler. -func (j *612EnumMyNullTypedEnumEnum) MarshalJSON() ([]byte, error) { +func (j *A612EnumMyNullTypedEnum) MarshalJSON() ([]byte, error) { return json.Marshal(j.Value) } - - // UnmarshalJSON implements json.Unmarshaler. -func (j *612EnumMyNullTypedEnumEnum) UnmarshalJSON(b []byte) error { +func (j *A612EnumMyNullTypedEnum) UnmarshalJSON(b []byte) error { var v struct { Value interface{} } - if err := json.Unmarshal(b, &v.Value); err != nil { return err } + if err := json.Unmarshal(b, &v.Value); err != nil { + return err + } var ok bool - for _, expected := range enumValues_612EnumMyNullTypedEnumEnum { - if reflect.DeepEqual(v.Value, expected) { ok = true; break } + for _, expected := range enumValues_A612EnumMyNullTypedEnum { + if reflect.DeepEqual(v.Value, expected) { + ok = true + break + } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_612EnumMyNullTypedEnumEnum, v.Value) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_A612EnumMyNullTypedEnum, v.Value) } - *j = 612EnumMyNullTypedEnumEnum(v) + *j = A612EnumMyNullTypedEnum(v) return nil } +type A612EnumMyNumberTypedEnum float64 -type 612EnumMyNumberTypedEnumEnum float64 -var enumValues_612EnumMyNumberTypedEnumEnum = []interface {}{ - 1, - 2, - 3, +var enumValues_A612EnumMyNumberTypedEnum = []interface{}{ + 1, + 2, + 3, } // UnmarshalJSON implements json.Unmarshaler. -func (j *612EnumMyNumberTypedEnumEnum) UnmarshalJSON(b []byte) error { +func (j *A612EnumMyNumberTypedEnum) UnmarshalJSON(b []byte) error { var v float64 - if err := json.Unmarshal(b, &v); err != nil { return err } + if err := json.Unmarshal(b, &v); err != nil { + return err + } var ok bool - for _, expected := range enumValues_612EnumMyNumberTypedEnumEnum { - if reflect.DeepEqual(v, expected) { ok = true; break } + for _, expected := range enumValues_A612EnumMyNumberTypedEnum { + if reflect.DeepEqual(v, expected) { + ok = true + break + } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_612EnumMyNumberTypedEnumEnum, v) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_A612EnumMyNumberTypedEnum, v) } - *j = 612EnumMyNumberTypedEnumEnum(v) + *j = A612EnumMyNumberTypedEnum(v) return nil } +type A612EnumMyStringTypedEnum string -type 612EnumMyStringTypedEnumEnum string -var enumValues_612EnumMyStringTypedEnumEnum = []interface {}{ - "red", - "blue", - "green", +var enumValues_A612EnumMyStringTypedEnum = []interface{}{ + "red", + "blue", + "green", } // UnmarshalJSON implements json.Unmarshaler. -func (j *612EnumMyStringTypedEnumEnum) UnmarshalJSON(b []byte) error { +func (j *A612EnumMyStringTypedEnum) UnmarshalJSON(b []byte) error { var v string - if err := json.Unmarshal(b, &v); err != nil { return err } + if err := json.Unmarshal(b, &v); err != nil { + return err + } var ok bool - for _, expected := range enumValues_612EnumMyStringTypedEnumEnum { - if reflect.DeepEqual(v, expected) { ok = true; break } + for _, expected := range enumValues_A612EnumMyStringTypedEnum { + if reflect.DeepEqual(v, expected) { + ok = true + break + } } if !ok { - return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_612EnumMyStringTypedEnumEnum, v) + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_A612EnumMyStringTypedEnum, v) } - *j = 612EnumMyStringTypedEnumEnum(v) + *j = A612EnumMyStringTypedEnum(v) return nil } +const A612EnumMyStringTypedEnumRed A612EnumMyStringTypedEnum = "red" +const A612EnumMyStringTypedEnumBlue A612EnumMyStringTypedEnum = "blue" +const A612EnumMyStringTypedEnumGreen A612EnumMyStringTypedEnum = "green" -const 612EnumMyStringTypedEnumEnumRed 612EnumMyStringTypedEnumEnum = "red" -const 612EnumMyStringTypedEnumEnumBlue 612EnumMyStringTypedEnumEnum = "blue" -const 612EnumMyStringTypedEnumEnumGreen 612EnumMyStringTypedEnumEnum = "green" -type 612Enum struct { +type A612Enum struct { // MyBooleanTypedEnum corresponds to the JSON schema field "myBooleanTypedEnum". - MyBooleanTypedEnum *612EnumMyBooleanTypedEnumEnum `json:"myBooleanTypedEnum,omitempty"` + MyBooleanTypedEnum *A612EnumMyBooleanTypedEnum `json:"myBooleanTypedEnum,omitempty"` // MyBooleanUntypedEnum corresponds to the JSON schema field // "myBooleanUntypedEnum". - MyBooleanUntypedEnum *612EnumMyBooleanTypedEnumEnum `json:"myBooleanUntypedEnum,omitempty"` + MyBooleanUntypedEnum *A612EnumMyBooleanTypedEnum `json:"myBooleanUntypedEnum,omitempty"` // MyMixedUntypedEnum corresponds to the JSON schema field "myMixedUntypedEnum". - MyMixedUntypedEnum *612EnumMyMixedUntypedEnumEnum `json:"myMixedUntypedEnum,omitempty"` + MyMixedUntypedEnum *A612EnumMyMixedUntypedEnum `json:"myMixedUntypedEnum,omitempty"` // MyNullTypedEnum corresponds to the JSON schema field "myNullTypedEnum". - MyNullTypedEnum *612EnumMyNullTypedEnumEnum `json:"myNullTypedEnum,omitempty"` + MyNullTypedEnum *A612EnumMyNullTypedEnum `json:"myNullTypedEnum,omitempty"` // MyNullUntypedEnum corresponds to the JSON schema field "myNullUntypedEnum". - MyNullUntypedEnum *612EnumMyNullTypedEnumEnum `json:"myNullUntypedEnum,omitempty"` + MyNullUntypedEnum *A612EnumMyNullTypedEnum `json:"myNullUntypedEnum,omitempty"` // MyNumberTypedEnum corresponds to the JSON schema field "myNumberTypedEnum". - MyNumberTypedEnum *612EnumMyNumberTypedEnumEnum `json:"myNumberTypedEnum,omitempty"` + MyNumberTypedEnum *A612EnumMyNumberTypedEnum `json:"myNumberTypedEnum,omitempty"` // MyNumberUntypedEnum corresponds to the JSON schema field "myNumberUntypedEnum". - MyNumberUntypedEnum *612EnumMyNumberTypedEnumEnum `json:"myNumberUntypedEnum,omitempty"` + MyNumberUntypedEnum *A612EnumMyNumberTypedEnum `json:"myNumberUntypedEnum,omitempty"` // MyStringTypedEnum corresponds to the JSON schema field "myStringTypedEnum". - MyStringTypedEnum *612EnumMyStringTypedEnumEnum `json:"myStringTypedEnum,omitempty"` + MyStringTypedEnum *A612EnumMyStringTypedEnum `json:"myStringTypedEnum,omitempty"` // MyStringUntypedEnum corresponds to the JSON schema field "myStringUntypedEnum". - MyStringUntypedEnum *612EnumMyStringTypedEnumEnum `json:"myStringUntypedEnum,omitempty"` -} \ No newline at end of file + MyStringUntypedEnum *A612EnumMyStringTypedEnum `json:"myStringUntypedEnum,omitempty"` +} diff --git a/tests/data/validation/6.5.3_requiredFields.go.output b/tests/data/validation/6.5.3_requiredFields.go.output index fa4aac1d..b9b9021f 100644 --- a/tests/data/validation/6.5.3_requiredFields.go.output +++ b/tests/data/validation/6.5.3_requiredFields.go.output @@ -1,52 +1,59 @@ // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. package test + import "fmt" import "encoding/json" -type 653RequiredFieldsMyObject struct { +type A653RequiredFieldsMyObject struct { // MyNestedObjectString corresponds to the JSON schema field // "myNestedObjectString". MyNestedObjectString string `json:"myNestedObjectString"` } // UnmarshalJSON implements json.Unmarshaler. -func (j *653RequiredFieldsMyObject) UnmarshalJSON(b []byte) error { +func (j *A653RequiredFieldsMyObject) UnmarshalJSON(b []byte) error { var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { return err } + if err := json.Unmarshal(b, &raw); err != nil { + return err + } if v, ok := raw["myNestedObjectString"]; !ok || v == nil { return fmt.Errorf("field myNestedObjectString: required") } - type Plain 653RequiredFieldsMyObject + type Plain A653RequiredFieldsMyObject var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = 653RequiredFieldsMyObject(plain) + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = A653RequiredFieldsMyObject(plain) return nil } - -type 653RequiredFieldsMyObjectArrayElem struct { +type A653RequiredFieldsMyObjectArrayElem struct { // MyNestedObjectString corresponds to the JSON schema field // "myNestedObjectString". MyNestedObjectString string `json:"myNestedObjectString"` } // UnmarshalJSON implements json.Unmarshaler. -func (j *653RequiredFieldsMyObjectArrayElem) UnmarshalJSON(b []byte) error { +func (j *A653RequiredFieldsMyObjectArrayElem) UnmarshalJSON(b []byte) error { var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { return err } + if err := json.Unmarshal(b, &raw); err != nil { + return err + } if v, ok := raw["myNestedObjectString"]; !ok || v == nil { return fmt.Errorf("field myNestedObjectString: required") } - type Plain 653RequiredFieldsMyObjectArrayElem + type Plain A653RequiredFieldsMyObjectArrayElem var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = 653RequiredFieldsMyObjectArrayElem(plain) + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = A653RequiredFieldsMyObjectArrayElem(plain) return nil } - -type 653RequiredFields struct { +type A653RequiredFields struct { // MyBoolean corresponds to the JSON schema field "myBoolean". MyBoolean bool `json:"myBoolean"` @@ -66,10 +73,10 @@ type 653RequiredFields struct { MyNumberArray []float64 `json:"myNumberArray"` // MyObject corresponds to the JSON schema field "myObject". - MyObject 653RequiredFieldsMyObject `json:"myObject"` + MyObject A653RequiredFieldsMyObject `json:"myObject"` // MyObjectArray corresponds to the JSON schema field "myObjectArray". - MyObjectArray []653RequiredFieldsMyObjectArrayElem `json:"myObjectArray"` + MyObjectArray []A653RequiredFieldsMyObjectArrayElem `json:"myObjectArray"` // MyString corresponds to the JSON schema field "myString". MyString string `json:"myString"` @@ -79,9 +86,11 @@ type 653RequiredFields struct { } // UnmarshalJSON implements json.Unmarshaler. -func (j *653RequiredFields) UnmarshalJSON(b []byte) error { +func (j *A653RequiredFields) UnmarshalJSON(b []byte) error { var raw map[string]interface{} - if err := json.Unmarshal(b, &raw); err != nil { return err } + if err := json.Unmarshal(b, &raw); err != nil { + return err + } if v, ok := raw["myBoolean"]; !ok || v == nil { return fmt.Errorf("field myBoolean: required") } @@ -112,10 +121,11 @@ func (j *653RequiredFields) UnmarshalJSON(b []byte) error { if v, ok := raw["myStringArray"]; !ok || v == nil { return fmt.Errorf("field myStringArray: required") } - type Plain 653RequiredFields + type Plain A653RequiredFields var plain Plain - if err := json.Unmarshal(b, &plain); err != nil { return err } - *j = 653RequiredFields(plain) + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = A653RequiredFields(plain) return nil } - diff --git a/tests/integration_test.go b/tests/integration_test.go index b781f5cc..23295967 100644 --- a/tests/integration_test.go +++ b/tests/integration_test.go @@ -113,6 +113,7 @@ func testExampleFile(t *testing.T, cfg generator.Config, fileName string) { outputName += ".output" goldenFileName := filepath.Join(filepath.Dir(fileName), outputName) + t.Logf("Using golden data in %s", mustAbs(goldenFileName)) goldenData, err := ioutil.ReadFile(goldenFileName) if err != nil { @@ -120,7 +121,7 @@ func testExampleFile(t *testing.T, cfg generator.Config, fileName string) { t.Fatal(err) } goldenData = source - t.Logf("Writing golden data to %s", goldenFileName) + t.Log("File does not exist; creating it") if err = ioutil.WriteFile(goldenFileName, goldenData, 0655); err != nil { t.Fatal(err) }