diff --git a/CHANGELOG.md b/CHANGELOG.md index a3dae9f..0e7aeef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [0.4.1] - 2017-02-19 +### Fixed +- enum in array bugs +- var name bugs + ## [0.4.0] - 2017-01-23 ### Fixed - type name bugs @@ -44,7 +49,8 @@ - pre-release -[0.3.1]: https://github.com/aaharu/schemarshal/compare/0.3.0...0.4.0 +[0.4.1]: https://github.com/aaharu/schemarshal/compare/0.4.0...0.4.1 +[0.4.0]: https://github.com/aaharu/schemarshal/compare/0.3.0...0.4.0 [0.3.0]: https://github.com/aaharu/schemarshal/compare/0.2.1...0.3.0 [0.2.1]: https://github.com/aaharu/schemarshal/compare/0.2.0...0.2.1 [0.2.0]: https://github.com/aaharu/schemarshal/compare/0.1.0...0.2.0 diff --git a/README.md b/README.md index 631c437..f90b4af 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,17 @@ OPTIONS Show version. ``` +## TODO + +- [ ] use go/ast + ## Examples ```bash schemarshal -p sample test_data/a.json ``` ```go -// generated by schemarshal 0.3.0 `schemarshal -p sample test_data/a.json` +// generated by schemarshal 0.4.1 `./schemarshal -p sample test_data/a.json` // DO NOT RECOMMEND EDITING THIS FILE. package sample @@ -47,16 +51,16 @@ type A struct { Test []int `json:"test,omitempty"` Test2 time.Time `json:"test2,omitempty"` PhoneNumber []struct { - Hoge struct { + Location string `json:"location"` + Code int `json:"code"` + Hoge struct { Aaa bool `json:"aaa,omitempty"` } `json:"hoge,omitempty"` - Fuga map[string]interface{} `json:"fuga,omitempty"` - Location string `json:"location"` - Code int `json:"code"` + Fuga map[string]interface{} `json:"fuga,omitempty"` } `json:"phoneNumber"` Address struct { - City *string `json:"city"` StreetAddress string `json:"streetAddress"` + City *string `json:"city"` } `json:"address"` } @@ -66,19 +70,20 @@ type A struct { curl -s "https://raw.githubusercontent.com/aaharu/schemarshal/master/test_data/disk.json" | schemarshal ``` ```go -// generated by schemarshal 0.3.0 `schemarshal` +// generated by schemarshal 0.4.1 `schemarshal` // DO NOT RECOMMEND EDITING THIS FILE. package main import ( "fmt" - "strings" + "strconv" ) -type SchemarshalType struct { - Device string `json:"device"` - Type TypeEnum `json:"type"` +type Disk struct { + Type TypeEnum `json:"type"` + Device string `json:"device"` + Test []TestEnum `json:"test,omitempty"` } type TypeEnum int @@ -86,13 +91,38 @@ type TypeEnum int const ( TypeEnumDisk TypeEnum = iota TypeEnumDisk2 + TypeEnumABC ) func (enum TypeEnum) MarshalJSON() ([]byte, error) { - var enumList = []interface{}{"disk", "disk2"} + var enumList = []interface{}{ + "disk", + "disk2", + "a\"b\\c", + } + switch v := enumList[enum].(type) { + case string: + return []byte(strconv.Quote(v)), nil + default: + return []byte(fmt.Sprintf("%v", v)), nil + } +} + +type TestEnum int + +const ( + TestEnumX TestEnum = iota + TestEnumY +) + +func (enum TestEnum) MarshalJSON() ([]byte, error) { + var enumList = []interface{}{ + "x", + "y", + } switch v := enumList[enum].(type) { case string: - return []byte(fmt.Sprintf("\"%v\"", strings.Replace(v, `"`, `\"`, -1))), nil + return []byte(strconv.Quote(v)), nil default: return []byte(fmt.Sprintf("%v", v)), nil } diff --git a/codegen/generator.go b/codegen/generator.go index cfc3b7f..7722187 100644 --- a/codegen/generator.go +++ b/codegen/generator.go @@ -8,7 +8,7 @@ import ( "bytes" "fmt" "go/format" - "strings" + "strconv" "github.com/aaharu/schemarshal/utils" "github.com/aaharu/schemarshal/version" @@ -79,29 +79,27 @@ func (g *Generator) Generate() ([]byte, error) { buf.WriteString("const (\n") for i := range enum { if i == 0 { - buf.WriteString(typeName + utils.UpperCamelCase(fmt.Sprintf("%v", enum[0])) + " " + typeName + " = iota\n") + buf.WriteString(utils.UpperCamelCase(typeName+" "+fmt.Sprintf("%v", enum[0])) + " " + typeName + " = iota\n") } else { - buf.WriteString(typeName + utils.UpperCamelCase(fmt.Sprintf("%v", enum[i])) + "\n") + buf.WriteString(utils.UpperCamelCase(typeName+" "+fmt.Sprintf("%v", enum[i])) + "\n") } } buf.WriteString(")\n") buf.WriteString("func (enum " + typeName + ") MarshalJSON() ([]byte, error) {\n") - buf.WriteString("var enumList = []interface{}{") + buf.WriteString("var enumList = []interface{}{\n") for i := range enum { switch v := enum[i].(type) { case string: - buf.WriteString(`"`) - buf.WriteString(strings.Replace(v, `"`, `\"`, -1)) - buf.WriteString(`"`) + buf.WriteString(strconv.Quote(v)) default: buf.WriteString(fmt.Sprintf("%v", v)) } - buf.WriteString(",") + buf.WriteString(",\n") } buf.WriteString("}\n") buf.WriteString("switch v:= enumList[enum].(type) {\n") buf.WriteString("case string:\n") - buf.WriteString("return []byte(fmt.Sprintf(\"\\\"%v\\\"\", strings.Replace(v, `\"`, `\\\"`, -1))), nil\n") + buf.WriteString("return []byte(strconv.Quote(v)), nil\n") buf.WriteString("default:\n") buf.WriteString("return []byte(fmt.Sprintf(\"%v\", v)), nil\n") buf.WriteString("}\n") diff --git a/codegen/jsonschema.go b/codegen/jsonschema.go index edf33bd..2d73d83 100644 --- a/codegen/jsonschema.go +++ b/codegen/jsonschema.go @@ -75,7 +75,7 @@ func (js *JSONSchema) Parse(fieldName string) (*JSONType, EnumSpec, ImportSpec, } enumList[enumName] = js.schema.Enum t.enumType = enumName - imports[`"strings"`] = "" + imports[`"strconv"`] = "" imports[`"fmt"`] = "" } return t, enumList, imports, nil @@ -94,7 +94,7 @@ func (js *JSONSchema) Parse(fieldName string) (*JSONType, EnumSpec, ImportSpec, enumName := utils.EnumTypeName(fieldName) enumList[enumName] = js.schema.Enum t.enumType = enumName - imports[`"strings"`] = "" + imports[`"strconv"`] = "" imports[`"fmt"`] = "" } return t, enumList, imports, nil @@ -135,7 +135,7 @@ func (js *JSONSchema) Parse(fieldName string) (*JSONType, EnumSpec, ImportSpec, enumName := utils.EnumTypeName(fieldName) enumList[enumName] = js.schema.Enum t.enumType = enumName - imports[`"strings"`] = "" + imports[`"strconv"`] = "" imports[`"fmt"`] = "" } return t, enumList, imports, nil @@ -150,11 +150,21 @@ func (js *JSONSchema) Parse(fieldName string) (*JSONType, EnumSpec, ImportSpec, if inPrimitiveTypes(schema.NullType, js.schema.Type) { t.nullable = true } - itemType, _, itemImports, err := NewSchema(js.schema.Items.Schemas[0]).Parse("") + itemType, itemEnumList, itemImports, err := NewSchema(js.schema.Items.Schemas[0]).Parse(fieldName) if err != nil { return nil, nil, nil, err } t.itemType = itemType + for k, v := range itemEnumList { + if _, ok := enumList[k]; ok == true { + // FIXME: unsupported + err := fmt.Errorf("unsupported json") + return t, enumList, imports, err + } + enumList[k] = v + imports[`"strconv"`] = "" + imports[`"fmt"`] = "" + } for k, v := range itemImports { imports[k] = v } diff --git a/test_data/disk.json b/test_data/disk.json index c7dd941..0151cc3 100644 --- a/test_data/disk.json +++ b/test_data/disk.json @@ -3,11 +3,18 @@ "properties": { "type": { "type": "string", - "enum": [ "disk", "disk2" ] + "enum": [ "disk", "disk2", "a\"b\\c" ] }, "device": { "type": "string", "pattern": "^/dev/[^/]+(/[^/]+)*$" + }, + "test": { + "type": "array", + "items": { + "type": "string", + "enum": [ "x", "y" ] + } } }, "required": [ "type", "device" ], diff --git a/utils/converter.go b/utils/converter.go index 162add2..975d142 100644 --- a/utils/converter.go +++ b/utils/converter.go @@ -7,14 +7,27 @@ package utils import ( "os" "path" + "regexp" "strings" ) +var ( + alpha = regexp.MustCompile(`[a-zA-Z]+`) + notAlphaNum = regexp.MustCompile(`[^a-zA-Z0-9]`) +) + // UpperCamelCase returns the string to upper camel case func UpperCamelCase(str string) string { - str = strings.Replace(str, "-", " ", -1) - str = strings.Replace(str, "_", " ", -1) - return strings.Replace(strings.Title(str), " ", "", -1) + matches := notAlphaNum.Split(str, -1) + result := "" + for i, m := range matches { + if i == 0 { + result += strings.Title(alpha.FindString(m)) + continue + } + result += strings.Title(m) + } + return result } // FileName returns file-name without ext diff --git a/utils/converter_test.go b/utils/converter_test.go index 2a84dce..3338514 100644 --- a/utils/converter_test.go +++ b/utils/converter_test.go @@ -10,8 +10,20 @@ import ( ) func TestUpperCamelCase(t *testing.T) { - actual := UpperCamelCase("address") - expected := "Address" + actual := UpperCamelCase("1st address") + expected := "StAddress" + if actual != expected { + t.Errorf("got %v\nwant %v", actual, expected) + } + + actual = UpperCamelCase("address 1st") + expected = "Address1st" + if actual != expected { + t.Errorf("got %v\nwant %v", actual, expected) + } + + actual = UpperCamelCase("quote\" slash/") + expected = "QuoteSlash" if actual != expected { t.Errorf("got %v\nwant %v", actual, expected) } diff --git a/version/version.go b/version/version.go index 0c7c0a8..81044b0 100644 --- a/version/version.go +++ b/version/version.go @@ -7,7 +7,7 @@ package version import "fmt" // Version of schemarshal -const Version = "0.4.0" +const Version = "0.4.1" // String return ` ` func String() string { diff --git a/version/version_test.go b/version/version_test.go index 390987d..13f2df5 100644 --- a/version/version_test.go +++ b/version/version_test.go @@ -8,7 +8,7 @@ import "testing" func TestString(t *testing.T) { actual := String() - expected := "schemarshal 0.4.0" + expected := "schemarshal 0.4.1" if actual != expected { t.Errorf("got %v\nwant %v", actual, expected) }