From 1d8b1b1f4cb7e006612f3cd7abb6904030208920 Mon Sep 17 00:00:00 2001 From: Alexander Hedges Date: Fri, 26 Mar 2021 13:13:55 +0100 Subject: [PATCH 1/3] Unmarshal into a *map instead of a map This allows us to distinguish between `null` and `{}`. --- pkg/codegen/templates/additional-properties.tmpl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/codegen/templates/additional-properties.tmpl b/pkg/codegen/templates/additional-properties.tmpl index 46b66c86e2..447f577ebe 100644 --- a/pkg/codegen/templates/additional-properties.tmpl +++ b/pkg/codegen/templates/additional-properties.tmpl @@ -19,23 +19,24 @@ func (a *{{.TypeName}}) Set(fieldName string, value {{$addType}}) { // Override default JSON handling for {{.TypeName}} to handle AdditionalProperties func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } + + if object != nil { {{range .Schema.Properties}} - if raw, found := object["{{.JsonFieldName}}"]; found { + if raw, found := (*object)["{{.JsonFieldName}}"]; found { err = json.Unmarshal(raw, &a.{{.GoFieldName}}) if err != nil { return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) } - delete(object, "{{.JsonFieldName}}") + delete(*object, "{{.JsonFieldName}}") } {{end}} - if len(object) != 0 { a.AdditionalProperties = make(map[string]{{$addType}}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal {{$addType}} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { From dcdc3ef86459340dc80c9132516c4c4dba2a3cc4 Mon Sep 17 00:00:00 2001 From: Alexander Hedges Date: Tue, 9 Nov 2021 10:15:42 +0100 Subject: [PATCH 2/3] Run go generate --- internal/test/components/components.gen.go | 171 +++++++++++---------- internal/test/issues/issue-52/issue.gen.go | 7 +- pkg/codegen/templates/templates.gen.go | 11 +- 3 files changed, 100 insertions(+), 89 deletions(-) diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go index 54f9eb2e11..6531f1d123 100644 --- a/internal/test/components/components.gen.go +++ b/internal/test/components/components.gen.go @@ -142,15 +142,16 @@ func (a *ParamsWithAddPropsParams_P1) Set(fieldName string, value interface{}) { // Override default JSON handling for ParamsWithAddPropsParams_P1 to handle AdditionalProperties func (a *ParamsWithAddPropsParams_P1) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if len(object) != 0 { + if object != nil { + a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -195,15 +196,16 @@ func (a *ParamsWithAddPropsParams_P2_Inner) Set(fieldName string, value string) // Override default JSON handling for ParamsWithAddPropsParams_P2_Inner to handle AdditionalProperties func (a *ParamsWithAddPropsParams_P2_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if len(object) != 0 { + if object != nil { + a.AdditionalProperties = make(map[string]string) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal string err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -248,31 +250,32 @@ func (a *BodyWithAddPropsJSONBody) Set(fieldName string, value interface{}) { // Override default JSON handling for BodyWithAddPropsJSONBody to handle AdditionalProperties func (a *BodyWithAddPropsJSONBody) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if raw, found := object["inner"]; found { - err = json.Unmarshal(raw, &a.Inner) - if err != nil { - return fmt.Errorf("error reading 'inner': %w", err) + if object != nil { + + if raw, found := (*object)["inner"]; found { + err = json.Unmarshal(raw, &a.Inner) + if err != nil { + return fmt.Errorf("error reading 'inner': %w", err) + } + delete(*object, "inner") } - delete(object, "inner") - } - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return fmt.Errorf("error reading 'name': %w", err) + if raw, found := (*object)["name"]; found { + err = json.Unmarshal(raw, &a.Name) + if err != nil { + return fmt.Errorf("error reading 'name': %w", err) + } + delete(*object, "name") } - delete(object, "name") - } - if len(object) != 0 { a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -327,15 +330,16 @@ func (a *BodyWithAddPropsJSONBody_Inner) Set(fieldName string, value int) { // Override default JSON handling for BodyWithAddPropsJSONBody_Inner to handle AdditionalProperties func (a *BodyWithAddPropsJSONBody_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if len(object) != 0 { + if object != nil { + a.AdditionalProperties = make(map[string]int) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal int err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -380,39 +384,40 @@ func (a *AdditionalPropertiesObject1) Set(fieldName string, value int) { // Override default JSON handling for AdditionalPropertiesObject1 to handle AdditionalProperties func (a *AdditionalPropertiesObject1) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if raw, found := object["id"]; found { - err = json.Unmarshal(raw, &a.Id) - if err != nil { - return fmt.Errorf("error reading 'id': %w", err) + if object != nil { + + if raw, found := (*object)["id"]; found { + err = json.Unmarshal(raw, &a.Id) + if err != nil { + return fmt.Errorf("error reading 'id': %w", err) + } + delete(*object, "id") } - delete(object, "id") - } - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return fmt.Errorf("error reading 'name': %w", err) + if raw, found := (*object)["name"]; found { + err = json.Unmarshal(raw, &a.Name) + if err != nil { + return fmt.Errorf("error reading 'name': %w", err) + } + delete(*object, "name") } - delete(object, "name") - } - if raw, found := object["optional"]; found { - err = json.Unmarshal(raw, &a.Optional) - if err != nil { - return fmt.Errorf("error reading 'optional': %w", err) + if raw, found := (*object)["optional"]; found { + err = json.Unmarshal(raw, &a.Optional) + if err != nil { + return fmt.Errorf("error reading 'optional': %w", err) + } + delete(*object, "optional") } - delete(object, "optional") - } - if len(object) != 0 { a.AdditionalProperties = make(map[string]int) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal int err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -474,23 +479,24 @@ func (a *AdditionalPropertiesObject3) Set(fieldName string, value interface{}) { // Override default JSON handling for AdditionalPropertiesObject3 to handle AdditionalProperties func (a *AdditionalPropertiesObject3) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return fmt.Errorf("error reading 'name': %w", err) + if object != nil { + + if raw, found := (*object)["name"]; found { + err = json.Unmarshal(raw, &a.Name) + if err != nil { + return fmt.Errorf("error reading 'name': %w", err) + } + delete(*object, "name") } - delete(object, "name") - } - if len(object) != 0 { a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -540,31 +546,32 @@ func (a *AdditionalPropertiesObject4) Set(fieldName string, value interface{}) { // Override default JSON handling for AdditionalPropertiesObject4 to handle AdditionalProperties func (a *AdditionalPropertiesObject4) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if raw, found := object["inner"]; found { - err = json.Unmarshal(raw, &a.Inner) - if err != nil { - return fmt.Errorf("error reading 'inner': %w", err) + if object != nil { + + if raw, found := (*object)["inner"]; found { + err = json.Unmarshal(raw, &a.Inner) + if err != nil { + return fmt.Errorf("error reading 'inner': %w", err) + } + delete(*object, "inner") } - delete(object, "inner") - } - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return fmt.Errorf("error reading 'name': %w", err) + if raw, found := (*object)["name"]; found { + err = json.Unmarshal(raw, &a.Name) + if err != nil { + return fmt.Errorf("error reading 'name': %w", err) + } + delete(*object, "name") } - delete(object, "name") - } - if len(object) != 0 { a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -619,23 +626,24 @@ func (a *AdditionalPropertiesObject4_Inner) Set(fieldName string, value interfac // Override default JSON handling for AdditionalPropertiesObject4_Inner to handle AdditionalProperties func (a *AdditionalPropertiesObject4_Inner) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if raw, found := object["name"]; found { - err = json.Unmarshal(raw, &a.Name) - if err != nil { - return fmt.Errorf("error reading 'name': %w", err) + if object != nil { + + if raw, found := (*object)["name"]; found { + err = json.Unmarshal(raw, &a.Name) + if err != nil { + return fmt.Errorf("error reading 'name': %w", err) + } + delete(*object, "name") } - delete(object, "name") - } - if len(object) != 0 { a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal interface{} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { @@ -685,15 +693,16 @@ func (a *AdditionalPropertiesObject5) Set(fieldName string, value SchemaObject) // Override default JSON handling for AdditionalPropertiesObject5 to handle AdditionalProperties func (a *AdditionalPropertiesObject5) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if len(object) != 0 { + if object != nil { + a.AdditionalProperties = make(map[string]SchemaObject) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal SchemaObject err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go index a07a4a2057..b4cf2e634d 100644 --- a/internal/test/issues/issue-52/issue.gen.go +++ b/internal/test/issues/issue-52/issue.gen.go @@ -58,15 +58,16 @@ func (a *Document_Fields) Set(fieldName string, value Value) { // Override default JSON handling for Document_Fields to handle AdditionalProperties func (a *Document_Fields) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } - if len(object) != 0 { + if object != nil { + a.AdditionalProperties = make(map[string]Value) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal Value err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go index a7211f9b28..fe6db3aca9 100644 --- a/pkg/codegen/templates/templates.gen.go +++ b/pkg/codegen/templates/templates.gen.go @@ -23,23 +23,24 @@ func (a *{{.TypeName}}) Set(fieldName string, value {{$addType}}) { // Override default JSON handling for {{.TypeName}} to handle AdditionalProperties func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) + var object *map[string]json.RawMessage err := json.Unmarshal(b, &object) if err != nil { return err } + + if object != nil { {{range .Schema.Properties}} - if raw, found := object["{{.JsonFieldName}}"]; found { + if raw, found := (*object)["{{.JsonFieldName}}"]; found { err = json.Unmarshal(raw, &a.{{.GoFieldName}}) if err != nil { return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) } - delete(object, "{{.JsonFieldName}}") + delete(*object, "{{.JsonFieldName}}") } {{end}} - if len(object) != 0 { a.AdditionalProperties = make(map[string]{{$addType}}) - for fieldName, fieldBuf := range object { + for fieldName, fieldBuf := range *object { var fieldVal {{$addType}} err := json.Unmarshal(fieldBuf, &fieldVal) if err != nil { From d019b67667b307ba2c06cb5bdc192a24ef0a232a Mon Sep 17 00:00:00 2001 From: Alexander Hedges Date: Tue, 9 Nov 2021 14:09:53 +0100 Subject: [PATCH 3/3] Don't add extra newline --- internal/test/components/components.gen.go | 9 --------- internal/test/issues/issue-52/issue.gen.go | 1 - pkg/codegen/templates/additional-properties.tmpl | 15 +++++++-------- pkg/codegen/templates/templates.gen.go | 15 +++++++-------- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/internal/test/components/components.gen.go b/internal/test/components/components.gen.go index 6531f1d123..c9473ceb6b 100644 --- a/internal/test/components/components.gen.go +++ b/internal/test/components/components.gen.go @@ -149,7 +149,6 @@ func (a *ParamsWithAddPropsParams_P1) UnmarshalJSON(b []byte) error { } if object != nil { - a.AdditionalProperties = make(map[string]interface{}) for fieldName, fieldBuf := range *object { var fieldVal interface{} @@ -203,7 +202,6 @@ func (a *ParamsWithAddPropsParams_P2_Inner) UnmarshalJSON(b []byte) error { } if object != nil { - a.AdditionalProperties = make(map[string]string) for fieldName, fieldBuf := range *object { var fieldVal string @@ -257,7 +255,6 @@ func (a *BodyWithAddPropsJSONBody) UnmarshalJSON(b []byte) error { } if object != nil { - if raw, found := (*object)["inner"]; found { err = json.Unmarshal(raw, &a.Inner) if err != nil { @@ -337,7 +334,6 @@ func (a *BodyWithAddPropsJSONBody_Inner) UnmarshalJSON(b []byte) error { } if object != nil { - a.AdditionalProperties = make(map[string]int) for fieldName, fieldBuf := range *object { var fieldVal int @@ -391,7 +387,6 @@ func (a *AdditionalPropertiesObject1) UnmarshalJSON(b []byte) error { } if object != nil { - if raw, found := (*object)["id"]; found { err = json.Unmarshal(raw, &a.Id) if err != nil { @@ -486,7 +481,6 @@ func (a *AdditionalPropertiesObject3) UnmarshalJSON(b []byte) error { } if object != nil { - if raw, found := (*object)["name"]; found { err = json.Unmarshal(raw, &a.Name) if err != nil { @@ -553,7 +547,6 @@ func (a *AdditionalPropertiesObject4) UnmarshalJSON(b []byte) error { } if object != nil { - if raw, found := (*object)["inner"]; found { err = json.Unmarshal(raw, &a.Inner) if err != nil { @@ -633,7 +626,6 @@ func (a *AdditionalPropertiesObject4_Inner) UnmarshalJSON(b []byte) error { } if object != nil { - if raw, found := (*object)["name"]; found { err = json.Unmarshal(raw, &a.Name) if err != nil { @@ -700,7 +692,6 @@ func (a *AdditionalPropertiesObject5) UnmarshalJSON(b []byte) error { } if object != nil { - a.AdditionalProperties = make(map[string]SchemaObject) for fieldName, fieldBuf := range *object { var fieldVal SchemaObject diff --git a/internal/test/issues/issue-52/issue.gen.go b/internal/test/issues/issue-52/issue.gen.go index b4cf2e634d..88e505f74b 100644 --- a/internal/test/issues/issue-52/issue.gen.go +++ b/internal/test/issues/issue-52/issue.gen.go @@ -65,7 +65,6 @@ func (a *Document_Fields) UnmarshalJSON(b []byte) error { } if object != nil { - a.AdditionalProperties = make(map[string]Value) for fieldName, fieldBuf := range *object { var fieldVal Value diff --git a/pkg/codegen/templates/additional-properties.tmpl b/pkg/codegen/templates/additional-properties.tmpl index 447f577ebe..9b249a61da 100644 --- a/pkg/codegen/templates/additional-properties.tmpl +++ b/pkg/codegen/templates/additional-properties.tmpl @@ -25,15 +25,14 @@ func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error { return err } - if object != nil { -{{range .Schema.Properties}} - if raw, found := (*object)["{{.JsonFieldName}}"]; found { - err = json.Unmarshal(raw, &a.{{.GoFieldName}}) - if err != nil { - return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) + if object != nil { {{range .Schema.Properties}} + if raw, found := (*object)["{{.JsonFieldName}}"]; found { + err = json.Unmarshal(raw, &a.{{.GoFieldName}}) + if err != nil { + return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) + } + delete(*object, "{{.JsonFieldName}}") } - delete(*object, "{{.JsonFieldName}}") - } {{end}} a.AdditionalProperties = make(map[string]{{$addType}}) for fieldName, fieldBuf := range *object { diff --git a/pkg/codegen/templates/templates.gen.go b/pkg/codegen/templates/templates.gen.go index fe6db3aca9..a18b2f31a0 100644 --- a/pkg/codegen/templates/templates.gen.go +++ b/pkg/codegen/templates/templates.gen.go @@ -29,15 +29,14 @@ func (a *{{.TypeName}}) UnmarshalJSON(b []byte) error { return err } - if object != nil { -{{range .Schema.Properties}} - if raw, found := (*object)["{{.JsonFieldName}}"]; found { - err = json.Unmarshal(raw, &a.{{.GoFieldName}}) - if err != nil { - return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) + if object != nil { {{range .Schema.Properties}} + if raw, found := (*object)["{{.JsonFieldName}}"]; found { + err = json.Unmarshal(raw, &a.{{.GoFieldName}}) + if err != nil { + return fmt.Errorf("error reading '{{.JsonFieldName}}': %w", err) + } + delete(*object, "{{.JsonFieldName}}") } - delete(*object, "{{.JsonFieldName}}") - } {{end}} a.AdditionalProperties = make(map[string]{{$addType}}) for fieldName, fieldBuf := range *object {