Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle oneOf with primitive and null type #84

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (g *Generator) processSchema(schemaName string, schema *Schema) (typ string
schema.FixMissingTypeValue()
// if we have multiple schema types, the golang type will be interface{}
typ = "interface{}"
types, isMultiType := schema.MultiType()
types, isMultiType, pointer := schema.MultiType()
if len(types) > 0 {
for _, schemaType := range types {
name := schemaName
Expand All @@ -123,7 +123,7 @@ func (g *Generator) processSchema(schemaName string, schema *Schema) (typ string
return rv, nil
}
default:
rv, err := getPrimitiveTypeName(schemaType, "", false)
rv, err := getPrimitiveTypeName(schemaType, "", pointer)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -238,7 +238,7 @@ func (g *Generator) processObject(name string, schema *Schema) (typ string, err
}
// additionalProperties as either true (everything) or false (nothing)
if schema.AdditionalProperties != nil && schema.AdditionalProperties.AdditionalPropertiesBool != nil {
if *schema.AdditionalProperties.AdditionalPropertiesBool == true {
if *schema.AdditionalProperties.AdditionalPropertiesBool {
// everything is valid additional
subTyp := "map[string]interface{}"
f := Field{
Expand All @@ -258,7 +258,12 @@ func (g *Generator) processObject(name string, schema *Schema) (typ string, err
strct.AdditionalType = "false"
}
}
if len(strct.Fields) == 0 {
return "map[string]interface{}", nil
}

g.Structs[strct.Name] = strct

// objects are always a pointer
return getPrimitiveTypeName("object", name, true)
}
Expand All @@ -280,10 +285,19 @@ func getPrimitiveTypeName(schemaType string, subType string, pointer bool) (name
}
return "[]" + subType, nil
case "boolean":
if pointer {
return "*bool", nil
}
return "bool", nil
case "integer":
if pointer {
return "*int", nil
}
return "int", nil
case "number":
if pointer {
return "*float64", nil
}
return "float64", nil
case "null":
return "nil", nil
Expand All @@ -296,6 +310,9 @@ func getPrimitiveTypeName(schemaType string, subType string, pointer bool) (name
}
return subType, nil
case "string":
if pointer {
return "*string", nil
}
return "string", nil
}

Expand Down
23 changes: 19 additions & 4 deletions jsonschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,25 @@ func (schema *Schema) Type() (firstOrDefault string, multiple bool) {
}

// MultiType returns "type" as an array
func (schema *Schema) MultiType() ([]string, bool) {
func (schema *Schema) MultiType() (types []string, isMultiType bool, pointer bool) {
// We've got a single value, e.g. { "type": "object" }
if ts, ok := schema.TypeValue.(string); ok {
return []string{ts}, false
return []string{ts}, false, false
}

if len(schema.OneOf) > 0 {
rv := []string{}
optional := false
for _, t := range schema.OneOf {
if t.TypeValue == "null" {
optional = true
} else {
if s, ok := t.TypeValue.(string); ok {
rv = append(rv, s)
}
}
}
return rv, len(rv) > 1, optional
}

// We could have multiple types in the type value, e.g. { "type": [ "object", "array" ] }
Expand All @@ -164,10 +179,10 @@ func (schema *Schema) MultiType() ([]string, bool) {
rv = append(rv, s)
}
}
return rv, len(rv) > 1
return rv, len(rv) > 1, false
}

return nil, false
return nil, false, false
}

// GetRoot returns the root schema.
Expand Down
17 changes: 17 additions & 0 deletions test/oneofnull.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Simple",
"type": "object",
"properties": {
"optional_name": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
}
}
60 changes: 60 additions & 0 deletions test/oneofnull_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package test

import (
"encoding/json"
"testing"

gen "github.com/a-h/generate/test/oneofnull_gen"
)

func TestOneOfNullParsingValue(t *testing.T) {

noPropData := `{"optional_name": "v"}`

s := gen.Simple{}
err := json.Unmarshal([]byte(noPropData), &s)
if err != nil {
t.Fatal(err)
}

if s.OptionalName == nil {
t.Fatal("Field option_name should be initialized")
}

if *s.OptionalName != "v" {
t.Fatal("Field option_name should be `v`")
}

}

func TestOneOfNullParsingNull(t *testing.T) {

noPropData := `{"optional_name": null}`

s := gen.Simple{}
err := json.Unmarshal([]byte(noPropData), &s)
if err != nil {
t.Fatal(err)
}

if s.OptionalName != nil {
t.Fatal("Field option_name should be nil")
}

}

func TestOneOfNullParsingAbsent(t *testing.T) {

noPropData := `{}`

s := gen.Simple{}
err := json.Unmarshal([]byte(noPropData), &s)
if err != nil {
t.Fatal(err)
}

if s.OptionalName != nil {
t.Fatal("Field option_name should be nil")
}

}