├── .circleci └── config.yml ├── .gitignore ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── README.md ├── cmd └── jwg │ └── main.go ├── generator.go ├── generator_test.go ├── misc ├── fixture │ ├── a │ │ ├── model.go │ │ └── model_json.go │ ├── b │ │ ├── model.go │ │ └── model_json.go │ ├── c │ │ ├── model.go │ │ └── model_json.go │ ├── d │ │ ├── model.go │ │ └── model_json.go │ ├── e │ │ ├── model.go │ │ └── model_json.go │ ├── f │ │ ├── model.go │ │ └── model_json.go │ ├── g │ │ ├── model.go │ │ └── model_json.go │ ├── h │ │ ├── model.go │ │ └── model_json.go │ ├── i │ │ ├── model.go │ │ └── model_json.go │ ├── j │ │ ├── model.go │ │ ├── model_json.go │ │ └── model_test.go │ ├── k │ │ ├── model.go │ │ └── model_json.go │ ├── l │ │ ├── model.go │ │ └── model_json.go │ ├── m │ │ ├── model.go │ │ └── model_json.go │ ├── n │ │ ├── model.go │ │ └── model_json.go │ └── t │ │ ├── model.go │ │ └── model_json.go └── other │ ├── v1 │ └── model.go │ └── v2 │ └── model.go ├── setup.sh ├── test.sh └── usage_test.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: /go/src/github.com/favclip/jwg 5 | docker: 6 | - image: google/cloud-sdk:178.0.0 7 | environment: 8 | GOPATH: /go 9 | GOLANG_VERSION: 1.9.2 10 | steps: 11 | - run: 12 | name: PATH update 13 | command: | 14 | echo "export PATH=\$PATH:/go/bin:/usr/local/go/bin" >> $BASH_ENV 15 | cat $BASH_ENV 16 | - run: 17 | name: install go binary 18 | command: | 19 | echo $PATH 20 | /usr/bin/curl -o go.tar.gz https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz && \ 21 | tar -zxf go.tar.gz && \ 22 | mv go /usr/local && \ 23 | rm go.tar.gz 24 | 25 | - checkout 26 | 27 | - run: go get -u github.com/golang/dep/cmd/dep 28 | - run: ./setup.sh 29 | - run: ./test.sh 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | 4 | vendor/ 5 | build-cmd/ 6 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:cc1bd35607d54edc6e5420b5952e78d7c115ce1e167b80c8759c79ba7803a0ca" 6 | name = "github.com/favclip/genbase" 7 | packages = ["."] 8 | pruneopts = "" 9 | revision = "33e3f4f43761221e7ef1f0be35bad3711ae26cbd" 10 | version = "v1.0.0" 11 | 12 | [[projects]] 13 | branch = "travis-1.9" 14 | digest = "1:d45f5fe0f8bf6cd0bc592502e7e8ec647d769e55387fe326eb624d67282a7d15" 15 | name = "github.com/golang/lint" 16 | packages = [ 17 | ".", 18 | "golint", 19 | ] 20 | pruneopts = "" 21 | revision = "883fe33ffc4344bad1ecd881f61afd5ec5d80e0a" 22 | 23 | [[projects]] 24 | digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" 25 | name = "github.com/pmezard/go-difflib" 26 | packages = ["difflib"] 27 | pruneopts = "" 28 | revision = "792786c7400a136282c1664665ae0a8db921c6c2" 29 | version = "v1.0.0" 30 | 31 | [[projects]] 32 | branch = "master" 33 | digest = "1:1c7094a77c36fbbfd5a3da1151ccd6adcdef0bd7e02cca77b7f67ae4f1cbcf0e" 34 | name = "golang.org/x/tools" 35 | packages = [ 36 | "cmd/goimports", 37 | "go/ast/astutil", 38 | "go/gcexportdata", 39 | "go/internal/cgo", 40 | "go/internal/gcimporter", 41 | "go/internal/packagesdriver", 42 | "go/packages", 43 | "go/types/typeutil", 44 | "imports", 45 | "internal/fastwalk", 46 | "internal/gopathwalk", 47 | "internal/semver", 48 | ] 49 | pruneopts = "" 50 | revision = "b4b6fe2cb82970f144debbe03ecb71e340b15446" 51 | 52 | [solve-meta] 53 | analyzer-name = "dep" 54 | analyzer-version = 1 55 | input-imports = [ 56 | "github.com/favclip/genbase", 57 | "github.com/golang/lint/golint", 58 | "github.com/pmezard/go-difflib/difflib", 59 | "golang.org/x/tools/cmd/goimports", 60 | ] 61 | solver-name = "gps-cdcl" 62 | solver-version = 1 63 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 2 | # for detailed Gopkg.toml documentation. 3 | 4 | required = [ 5 | "golang.org/x/tools/cmd/goimports", 6 | "github.com/golang/lint/golint" 7 | ] 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 tv-asahi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jwg 2 | 3 | `JSON wrapper generator` or `json web go`. 4 | 5 | ## Description 6 | 7 | `jwg` can generate Web API friendly struct. 8 | 9 | We need a `lowerCamelCase` property name, not a `UpperCamelCase`. 10 | jwg generate json tag with lower camel case automatically. 11 | 12 | Another case, We need a access control of struct property in web app. 13 | 14 | ``` 15 | type User struct { 16 | Name string 17 | EncryptedPassword string // I want to hide this field! 18 | } 19 | ``` 20 | 21 | ``` 22 | user := &User { 23 | "go-chan", 24 | "5ch", 25 | } 26 | builder := NewUserJSONBuilder() 27 | builder.AddAll() 28 | builder.Remove(builder.EncryptedPassword) 29 | json, _ := builder.Marshal(user) 30 | // emit `{"name":"go-chan"}` 31 | fmt.Println(string(json)) 32 | ``` 33 | 34 | ### Example 35 | 36 | [from](https://github.com/favclip/jwg/blob/master/misc/fixture/a/model.go): 37 | 38 | ``` 39 | type Sample struct { 40 | Foo string 41 | } 42 | ``` 43 | 44 | [to](https://github.com/favclip/jwg/blob/master/misc/fixture/a/model_json.go): 45 | 46 | ``` 47 | // generated! 48 | type SampleJSON struct { 49 | Foo string `json:"foo,omitempty"` 50 | } 51 | ``` 52 | 53 | usage: 54 | 55 | ``` 56 | src := &Sample{"Foo!"} 57 | 58 | builder := NewSampleJSONBuilder() // generated! 59 | builder.AddAll() 60 | var jsonStruct *SampleJSON = builder.Convert(src) 61 | 62 | json, err := json.Marshal(jsonStruct) 63 | ``` 64 | 65 | [other example](https://github.com/favclip/jwg/blob/master/usage_test.go). 66 | 67 | ### With `go generate` 68 | 69 | ``` 70 | $ ls -la . 71 | total 16 72 | drwxr-xr-x@ 4 vvakame staff 136 1 27 17:27 . 73 | drwxr-xr-x@ 6 vvakame staff 204 1 27 13:14 .. 74 | -rw-r--r--@ 1 vvakame staff 366 1 27 17:27 model.go 75 | $ cat model.go 76 | //go:generate jwg -output model_json.go . 77 | 78 | package d 79 | 80 | // test for struct with tagged comment 81 | 82 | // +jwg 83 | type Sample struct { 84 | A string `json:"foo!" datastore:"-"` 85 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 86 | } 87 | $ go generate 88 | $ ls -la . 89 | total 16 90 | drwxr-xr-x@ 4 vvakame staff 136 1 27 17:27 . 91 | drwxr-xr-x@ 6 vvakame staff 204 1 27 13:14 .. 92 | -rw-r--r--@ 1 vvakame staff 366 1 27 17:27 model.go 93 | -rw-r--r--@ 1 vvakame staff 1549 1 27 17:27 model_json.go 94 | ``` 95 | 96 | ## Installation 97 | 98 | ``` 99 | $ go get github.com/favclip/jwg/cmd/jwg 100 | $ jwg 101 | Usage of jwg: 102 | jwg [flags] [directory] 103 | jwg [flags] files... # Must be a single package 104 | Flags: 105 | -output="": output file name; default srcdir/_string.go 106 | -type="": comma-separated list of type names; must be set 107 | ``` 108 | 109 | ## Command sample 110 | 111 | Model with type specific option. 112 | 113 | ``` 114 | $ cat misc/fixture/a/model.go 115 | package a 116 | 117 | // test for basic struct definition 118 | 119 | type Sample struct { 120 | Foo string 121 | } 122 | $ jwg -type Sample -output misc/fixture/a/model_json.go misc/fixture/a 123 | ``` 124 | 125 | Model with tagged comment. 126 | 127 | ``` 128 | $ cat misc/fixture/d/model.go 129 | package d 130 | 131 | // test for struct with tagged comment 132 | 133 | // +jwg 134 | type Sample struct { 135 | A string `json:"foo!" datastore:"-"` 136 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 137 | } 138 | 139 | type IgnoredSample struct { 140 | A string `json:"foo!" datastore:"-"` 141 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 142 | } 143 | $ jwg -output misc/fixture/d/model_json.go misc/fixture/d 144 | ``` 145 | -------------------------------------------------------------------------------- /cmd/jwg/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // from stringer. https://godoc.org/golang.org/x/tools/cmd/stringer 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io/ioutil" 9 | "log" 10 | "os" 11 | "path/filepath" 12 | "strings" 13 | 14 | "github.com/favclip/genbase" 15 | "github.com/favclip/jwg" 16 | ) 17 | 18 | var ( 19 | typeNames = flag.String("type", "", "comma-separated list of type names; must be set") 20 | output = flag.String("output", "", "output file name; default srcdir/_string.go") 21 | transcriptTags = flag.String("transcripttag", "", "comma-separated list of transcript struct tag; if you want to transcript swagger etc tag to new JSON struct") 22 | noOmitempty = flag.Bool("noOmitempty", false, "don't add omitempt tag to each field") 23 | noOmitemptyFieldTypeNames = flag.String("noOmitemptyFieldType", "", "comma-separated list of field type names to suppress default omitempty tag") 24 | ) 25 | 26 | // Usage is a replacement usage function for the flags package. 27 | func Usage() { 28 | fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 29 | fmt.Fprintf(os.Stderr, "\tjwg [flags] [directory]\n") 30 | fmt.Fprintf(os.Stderr, "\tjwg [flags] files... # Must be a single package\n") 31 | fmt.Fprintf(os.Stderr, "Flags:\n") 32 | flag.PrintDefaults() 33 | os.Exit(2) 34 | } 35 | 36 | func main() { 37 | log.SetFlags(0) 38 | log.SetPrefix("jwg: ") 39 | flag.Usage = Usage 40 | flag.Parse() 41 | 42 | // We accept either one directory or a list of files. Which do we have? 43 | args := flag.Args() 44 | if len(args) == 0 { 45 | // Default: process whole package in current directory. 46 | args = []string{"."} 47 | } 48 | 49 | // Parse the package once. 50 | var dir string 51 | var pInfo *genbase.PackageInfo 52 | var err error 53 | p := &genbase.Parser{SkipSemanticsCheck: true} 54 | if len(args) == 1 && isDirectory(args[0]) { 55 | dir = args[0] 56 | pInfo, err = p.ParsePackageDir(dir) 57 | if err != nil { 58 | log.Fatal(err) 59 | } 60 | } else { 61 | dir = filepath.Dir(args[0]) 62 | pInfo, err = p.ParsePackageFiles(args) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | } 67 | 68 | var typeInfos genbase.TypeInfos 69 | if len(*typeNames) == 0 { 70 | typeInfos = pInfo.CollectTaggedTypeInfos("+jwg") 71 | } else { 72 | typeInfos = pInfo.CollectTypeInfos(strings.Split(*typeNames, ",")) 73 | } 74 | 75 | if len(typeInfos) == 0 { 76 | flag.Usage() 77 | } 78 | 79 | var transcriptTagNames []string 80 | { 81 | for _, str := range strings.Split(*transcriptTags, ",") { 82 | if str == "" { 83 | continue 84 | } 85 | transcriptTagNames = append(transcriptTagNames, str) 86 | } 87 | } 88 | 89 | var noOmitemptyFieldTypes []string 90 | if len(*noOmitemptyFieldTypeNames) > 0 { 91 | noOmitemptyFieldTypes = strings.Split(*noOmitemptyFieldTypeNames, ",") 92 | } 93 | 94 | bu, err := jwg.Parse(pInfo, typeInfos, &jwg.ParseOptions{ 95 | TranscriptTagNames: transcriptTagNames, 96 | NoOmitempty: *noOmitempty, 97 | NoOmitemptyFieldTypes: noOmitemptyFieldTypes, 98 | }) 99 | if err != nil { 100 | log.Fatal(err) 101 | } 102 | 103 | // Format the output. 104 | src, err := bu.Emit(nil) 105 | if err != nil { 106 | log.Printf("warning: internal error: invalid Go generated: %s", err) 107 | log.Printf("warning: compile the package to analyze the error") 108 | } 109 | 110 | // Write to file. 111 | outputName := *output 112 | if outputName == "" { 113 | baseName := fmt.Sprintf("%s_json.go", typeInfos[0].Name()) 114 | outputName = filepath.Join(dir, strings.ToLower(baseName)) 115 | } 116 | err = ioutil.WriteFile(outputName, src, 0644) 117 | if err != nil { 118 | log.Fatalf("writing output: %s", err) 119 | } 120 | 121 | } 122 | 123 | // isDirectory reports whether the named file is a directory. 124 | func isDirectory(name string) bool { 125 | info, err := os.Stat(name) 126 | if err != nil { 127 | log.Fatal(err) 128 | } 129 | return info.IsDir() 130 | } 131 | -------------------------------------------------------------------------------- /generator.go: -------------------------------------------------------------------------------- 1 | package jwg 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | "unicode" 9 | 10 | "github.com/favclip/genbase" 11 | ) 12 | 13 | // ErrInvalidTranscriptTags means invalid transcriptTag included. 14 | var ErrInvalidTranscriptTags = errors.New("do not contains json tag in transcriptTagNames") 15 | 16 | // ParseOptions means options to Parse function. 17 | type ParseOptions struct { 18 | TranscriptTagNames []string 19 | NoOmitempty bool 20 | NoOmitemptyFieldTypes []string 21 | } 22 | 23 | // BuildSource represents source code of assembling.. 24 | type BuildSource struct { 25 | g *genbase.Generator 26 | pkg *genbase.PackageInfo 27 | typeInfos genbase.TypeInfos 28 | transcriptTagNames []string // e.g. swagger etc... copy struct tag to *JSON struct 29 | noOmitempty bool 30 | noOmitemptyFieldTypes []string 31 | 32 | Structs []*BuildStruct 33 | } 34 | 35 | // BuildStruct represents struct of assembling.. 36 | type BuildStruct struct { 37 | parent *BuildSource 38 | typeInfo *genbase.TypeInfo 39 | 40 | Fields []*BuildField 41 | } 42 | 43 | // BuildField represents field of BuildStruct. 44 | type BuildField struct { 45 | parent *BuildStruct 46 | fieldInfo *genbase.FieldInfo 47 | 48 | Name string 49 | Embed bool 50 | Tag *BuildTag 51 | TranscriptTags []string 52 | } 53 | 54 | // BuildTag represents tag of BuildField. 55 | type BuildTag struct { 56 | field *BuildField 57 | 58 | Name string 59 | Ignore bool // e.g. Secret string `json:"-"` 60 | OmitEmpty bool // e.g. Field int `json:",omitempty"` 61 | ShouldEmit bool // e.g. Field int `json:",shouldemit"` shouldemit is not official supported tag. 62 | String bool // e.g. Int64String int64 `json:",string"` 63 | } 64 | 65 | // Parse construct *BuildSource from package & type information. 66 | func Parse(pkg *genbase.PackageInfo, typeInfos genbase.TypeInfos, opts *ParseOptions) (*BuildSource, error) { 67 | bu := &BuildSource{ 68 | g: genbase.NewGenerator(pkg), 69 | pkg: pkg, 70 | typeInfos: typeInfos, 71 | } 72 | 73 | if opts != nil { 74 | for _, tagName := range opts.TranscriptTagNames { 75 | if tagName == "json" { 76 | return nil, ErrInvalidTranscriptTags 77 | } 78 | } 79 | 80 | bu.transcriptTagNames = opts.TranscriptTagNames 81 | bu.noOmitempty = opts.NoOmitempty 82 | bu.noOmitemptyFieldTypes = opts.NoOmitemptyFieldTypes 83 | } 84 | 85 | bu.g.AddImport("encoding/json", "") 86 | 87 | for _, typeInfo := range typeInfos { 88 | err := bu.parseStruct(typeInfo) 89 | if err != nil { 90 | return nil, err 91 | } 92 | } 93 | 94 | return bu, nil 95 | } 96 | 97 | func (b *BuildSource) parseStruct(typeInfo *genbase.TypeInfo) error { 98 | structType, err := typeInfo.StructType() 99 | if err != nil { 100 | return err 101 | } 102 | 103 | st := &BuildStruct{ 104 | parent: b, 105 | typeInfo: typeInfo, 106 | } 107 | 108 | for _, fieldInfo := range structType.FieldInfos() { 109 | if len := len(fieldInfo.Names); len == 0 { 110 | // embedded struct in outer struct or multiply field declarations 111 | // https://play.golang.org/p/bcxbdiMyP4 112 | typeName, err := genbase.ExprToBaseTypeName(fieldInfo.Type) 113 | if err != nil { 114 | return err 115 | } 116 | err = b.parseField(st, typeInfo, fieldInfo, typeName, true) 117 | if err != nil { 118 | return err 119 | } 120 | continue 121 | } else { 122 | for _, nameIdent := range fieldInfo.Names { 123 | err := b.parseField(st, typeInfo, fieldInfo, nameIdent.Name, false) 124 | if err != nil { 125 | return err 126 | } 127 | } 128 | } 129 | } 130 | 131 | b.Structs = append(b.Structs, st) 132 | 133 | return nil 134 | } 135 | 136 | func (b *BuildSource) parseField(st *BuildStruct, typeInfo *genbase.TypeInfo, fieldInfo *genbase.FieldInfo, name string, embed bool) error { 137 | field := &BuildField{ 138 | parent: st, 139 | fieldInfo: fieldInfo, 140 | Name: name, 141 | Embed: embed, 142 | } 143 | st.Fields = append(st.Fields, field) 144 | 145 | tag := &BuildTag{ 146 | field: field, 147 | } 148 | { 149 | typeName, err := genbase.ExprToTypeName(fieldInfo.Type) 150 | if err != nil { 151 | return err 152 | } 153 | if typeName == "int64" { 154 | tag.String = true 155 | } 156 | } 157 | field.Tag = tag 158 | if field.Embed { 159 | // do not emit tag name for embed struct in default behavior 160 | } else if strings.IndexFunc(field.Name, func(r rune) bool { return unicode.IsLower(r) }) == -1 { 161 | // lower char is not contains. 162 | // convert to lower case. 163 | // e.g. ID -> id 164 | tag.Name = strings.ToLower(field.Name) 165 | } else { 166 | tag.Name = strings.ToLower(field.Name[:1]) + field.Name[1:] 167 | } 168 | 169 | if fieldInfo.Tag != nil { 170 | tagText := fieldInfo.Tag.Value[1 : len(fieldInfo.Tag.Value)-1] 171 | tagKeys := genbase.GetKeys(tagText) 172 | structTag := reflect.StructTag(tagText) 173 | 174 | for _, key := range tagKeys { 175 | for _, target := range b.transcriptTagNames { 176 | if target == key { 177 | tag := structTag.Get(key) 178 | field.TranscriptTags = append(field.TranscriptTags, fmt.Sprintf(`%s:"%s"`, key, tag)) 179 | } 180 | } 181 | if key != "json" { 182 | continue 183 | } 184 | 185 | jsonTag := structTag.Get("json") 186 | if jsonTag == "-" { 187 | tag.Ignore = true 188 | continue 189 | } 190 | if idx := strings.Index(jsonTag, ","); idx == -1 { 191 | tag.Name = jsonTag 192 | } else { 193 | for idx != -1 || jsonTag != "" { 194 | value := jsonTag 195 | if idx != -1 { 196 | value = jsonTag[:idx] 197 | jsonTag = jsonTag[idx+1:] 198 | } else { 199 | jsonTag = jsonTag[len(value):] 200 | } 201 | idx = strings.Index(jsonTag, ",") 202 | 203 | if value == "omitempty" { 204 | tag.OmitEmpty = true 205 | } else if value == "shouldemit" { 206 | tag.ShouldEmit = true 207 | } else if value == "string" { 208 | tag.String = true 209 | } else if value != "" { 210 | if strings.IndexFunc(value, func(r rune) bool { return unicode.IsLower(r) }) == -1 { 211 | // lower char is not contains. 212 | // convert to lower case. 213 | // e.g. ID -> id 214 | tag.Name = strings.ToLower(value) 215 | } else { 216 | tag.Name = strings.ToLower(value[:1]) + value[1:] 217 | } 218 | } 219 | } 220 | } 221 | } 222 | } 223 | 224 | needImport, packageIdent := genbase.IsReferenceToOtherPackage(fieldInfo.Type) 225 | if needImport && tag.Ignore == false { 226 | importSpec := typeInfo.FileInfo.FindImportSpecByIdent(packageIdent) 227 | if importSpec != nil && importSpec.Name != nil { 228 | b.g.AddImport(importSpec.Path.Value, importSpec.Name.Name) 229 | } else if importSpec != nil { 230 | b.g.AddImport(importSpec.Path.Value, "") 231 | } 232 | } 233 | 234 | return nil 235 | } 236 | 237 | // Emit generate wrapper code. 238 | func (b *BuildSource) Emit(args *[]string) ([]byte, error) { 239 | b.g.PrintHeader("jwg", args) 240 | 241 | for _, st := range b.Structs { 242 | err := st.emit(b.g) 243 | if err != nil { 244 | return nil, err 245 | } 246 | } 247 | 248 | return b.g.Format() 249 | } 250 | 251 | func (st *BuildStruct) emit(g *genbase.Generator) error { 252 | g.Printf("// %[1]sJSON is jsonized struct for %[1]s.\n", st.Name()) 253 | 254 | // generate FooJSON struct from Foo struct 255 | g.Printf("type %sJSON struct {\n", st.Name()) 256 | for _, field := range st.Fields { 257 | if field.Tag.Ignore { 258 | continue 259 | } 260 | postfix := "" 261 | if field.WithJWG() { 262 | postfix = "JSON" 263 | } 264 | tagString := field.Tag.TagString() 265 | if len(field.TranscriptTags) != 0 { 266 | tagString += " " + strings.Join(field.TranscriptTags, " ") 267 | } 268 | if tagString != "" { 269 | tagString = fmt.Sprintf("`%s`", tagString) 270 | } 271 | if field.Embed { 272 | g.Printf("%s%s %s\n", field.fieldInfo.TypeName(), postfix, tagString) 273 | } else { 274 | g.Printf("%s %s%s %s\n", field.Name, field.fieldInfo.TypeName(), postfix, tagString) 275 | } 276 | } 277 | g.Printf("}\n\n") 278 | 279 | g.Printf("// %[1]sJSONList is synonym about []*%[1]sJSON.\n", st.Name()) 280 | g.Printf("type %[1]sJSONList []*%[1]sJSON\n\n", st.Name()) 281 | 282 | // generate property builder 283 | g.Printf("// %[1]sPropertyEncoder is property encoder for [1]sJSON.\n", st.Name()) 284 | g.Printf("type %[1]sPropertyEncoder func(src *%[1]s, dest *%[1]sJSON) error\n\n", st.Name()) 285 | g.Printf("// %[1]sPropertyDecoder is property decoder for [1]sJSON.\n", st.Name()) 286 | g.Printf("type %[1]sPropertyDecoder func(src *%[1]sJSON, dest *%[1]s) error\n\n", st.Name()) 287 | 288 | // generate property info 289 | g.Printf(` 290 | // %[1]sPropertyInfo stores property information. 291 | type %[1]sPropertyInfo struct { 292 | fieldName string 293 | jsonName string 294 | Encoder %[1]sPropertyEncoder 295 | Decoder %[1]sPropertyDecoder 296 | } 297 | 298 | // FieldName returns struct field name of property. 299 | func (info *%[1]sPropertyInfo) FieldName() string { 300 | return info.fieldName 301 | } 302 | 303 | // JSONName returns json field name of property. 304 | func (info *%[1]sPropertyInfo) JSONName() string { 305 | return info.jsonName 306 | } 307 | 308 | `, st.Name()) 309 | 310 | // generate json builder 311 | g.Printf("// %[1]sJSONBuilder convert between %[1]s to %[1]sJSON mutually.\n", st.Name()) 312 | g.Printf("type %sJSONBuilder struct {\n", st.Name()) 313 | g.Printf("_properties map[string]*%sPropertyInfo\n", st.Name()) 314 | g.Printf("_jsonPropertyMap map[string]*%sPropertyInfo\n", st.Name()) 315 | g.Printf("_structPropertyMap map[string]*%sPropertyInfo\n", st.Name()) 316 | for _, field := range st.Fields { 317 | if field.Tag.Ignore { 318 | continue 319 | } 320 | g.Printf("%s *%sPropertyInfo\n", field.Name, st.Name()) 321 | } 322 | g.Printf("}\n") 323 | 324 | // generate new json builder factory function 325 | g.Printf("// New%[1]sJSONBuilder make new %[1]sJSONBuilder.\n", st.Name()) 326 | g.Printf("func New%[1]sJSONBuilder() *%[1]sJSONBuilder {\n", st.Name()) 327 | g.Printf("jb := &%sJSONBuilder{\n", st.Name()) 328 | g.Printf("_properties: map[string]*%sPropertyInfo{},\n", st.Name()) 329 | g.Printf("_jsonPropertyMap: map[string]*%sPropertyInfo{},\n", st.Name()) 330 | g.Printf("_structPropertyMap: map[string]*%sPropertyInfo{},\n", st.Name()) 331 | for _, field := range st.Fields { 332 | if field.Tag.Ignore { 333 | continue 334 | } 335 | if field.Embed { 336 | if field.WithJWG() && field.IsPtr() { 337 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 338 | if err != nil { 339 | return err 340 | } 341 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 342 | fieldName: "%[2]s", 343 | jsonName: "%[4]s", 344 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 345 | if src == nil { 346 | return nil 347 | } else if src.%[2]s == nil { 348 | return nil 349 | } 350 | d, err := New%[3]sJSONBuilder().AddAll().Convert(src.%[2]s) 351 | if err != nil { 352 | return err 353 | } 354 | dest.%[2]sJSON = d 355 | return nil 356 | }, 357 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 358 | if src == nil { 359 | return nil 360 | } else if src.%[2]sJSON == nil { 361 | return nil 362 | } 363 | d, err := src.%[2]sJSON.Convert() 364 | if err != nil { 365 | return err 366 | } 367 | dest.%[2]s = d 368 | return nil 369 | }, 370 | }, 371 | `, st.Name(), field.Name, typeName, field.Tag.Name) 372 | } else if field.WithJWG() { 373 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 374 | if err != nil { 375 | return err 376 | } 377 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 378 | fieldName: "%[2]s", 379 | jsonName: "%[4]s", 380 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 381 | if src == nil { 382 | return nil 383 | } 384 | d, err := New%[3]sJSONBuilder().AddAll().Convert(&src.%[2]s) 385 | if err != nil { 386 | return err 387 | } 388 | dest.%[2]sJSON = *d 389 | return nil 390 | }, 391 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 392 | if src == nil { 393 | return nil 394 | } 395 | d, err := src.%[2]sJSON.Convert() 396 | if err != nil { 397 | return err 398 | } 399 | dest.%[2]s = *d 400 | return nil 401 | }, 402 | }, 403 | `, st.Name(), field.Name, typeName, field.Tag.Name) 404 | } else { 405 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 406 | fieldName: "%[2]s", 407 | jsonName: "%[3]s", 408 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 409 | if src == nil { 410 | return nil 411 | } 412 | dest.%[2]s = src.%[2]s 413 | return nil 414 | }, 415 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 416 | if src == nil { 417 | return nil 418 | } 419 | dest.%[2]s = src.%[2]s 420 | return nil 421 | }, 422 | }, 423 | `, st.Name(), field.Name, field.Tag.Name) 424 | } 425 | } else { 426 | if field.WithJWG() && field.IsPtrArrayPtr() { 427 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 428 | if err != nil { 429 | return err 430 | } 431 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 432 | fieldName: "%[2]s", 433 | jsonName: "%[4]s", 434 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 435 | if src == nil { 436 | return nil 437 | } else if src.%[2]s == nil { 438 | return nil 439 | } 440 | list, err := New%[3]sJSONBuilder().AddAll().ConvertList(*src.%[2]s) 441 | if err != nil { 442 | return err 443 | } 444 | dest.%[2]s = (*[]*%[3]sJSON)(&list) 445 | return nil 446 | }, 447 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 448 | if src == nil { 449 | return nil 450 | } else if src.%[2]s == nil { 451 | return nil 452 | } 453 | list := make([]*%[3]s, len(*src.%[2]s)) 454 | for idx, obj := range *src.%[2]s { 455 | if obj == nil { 456 | continue 457 | } 458 | d, err := obj.Convert() 459 | if err != nil { 460 | return err 461 | } 462 | list[idx] = d 463 | } 464 | dest.%[2]s = &list 465 | return nil 466 | }, 467 | }, 468 | `, st.Name(), field.Name, typeName, field.Tag.Name) 469 | } else if field.WithJWG() && field.IsPtrArray() { 470 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 471 | if err != nil { 472 | return err 473 | } 474 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 475 | fieldName: "%[2]s", 476 | jsonName: "%[4]s", 477 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 478 | if src == nil { 479 | return nil 480 | } else if src.%[2]s == nil { 481 | return nil 482 | } 483 | b := New%[3]sJSONBuilder().AddAll() 484 | list := make([]%[3]sJSON, len(*src.%[2]s)) 485 | for idx, obj := range *src.%[2]s { 486 | d, err := b.Convert(&obj) 487 | if err != nil { 488 | return err 489 | } 490 | list[idx] = *d 491 | } 492 | dest.%[2]s = &list 493 | return nil 494 | }, 495 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 496 | if src == nil { 497 | return nil 498 | } else if src.%[2]s == nil { 499 | return nil 500 | } 501 | list := make([]%[3]s, len(*src.%[2]s)) 502 | for idx, obj := range *src.%[2]s { 503 | d, err := obj.Convert() 504 | if err != nil { 505 | return err 506 | } 507 | list[idx] = *d 508 | } 509 | dest.%[2]s = &list 510 | return nil 511 | }, 512 | }, 513 | `, st.Name(), field.Name, typeName, field.Tag.Name) 514 | } else if field.WithJWG() && field.IsArrayPtr() { 515 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 516 | if err != nil { 517 | return err 518 | } 519 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 520 | fieldName: "%[2]s", 521 | jsonName: "%[4]s", 522 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 523 | if src == nil { 524 | return nil 525 | } 526 | list, err := New%[3]sJSONBuilder().AddAll().ConvertList(src.%[2]s) 527 | if err != nil { 528 | return err 529 | } 530 | dest.%[2]s = ([]*%[3]sJSON)(list) 531 | return nil 532 | }, 533 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 534 | if src == nil { 535 | return nil 536 | } 537 | list := make([]*%[3]s, len(src.%[2]s)) 538 | for idx, obj := range src.%[2]s { 539 | if obj == nil { 540 | continue 541 | } 542 | d, err := obj.Convert() 543 | if err != nil { 544 | return err 545 | } 546 | list[idx] = d 547 | } 548 | dest.%[2]s = list 549 | return nil 550 | }, 551 | }, 552 | `, st.Name(), field.Name, typeName, field.Tag.Name) 553 | } else if field.WithJWG() && field.IsArray() { 554 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 555 | if err != nil { 556 | return err 557 | } 558 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 559 | fieldName: "%[2]s", 560 | jsonName: "%[4]s", 561 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 562 | if src == nil { 563 | return nil 564 | } 565 | b := New%[3]sJSONBuilder().AddAll() 566 | list := make([]%[3]sJSON, len(src.%[2]s)) 567 | for idx, obj := range src.%[2]s { 568 | d, err := b.Convert(&obj) 569 | if err != nil { 570 | return err 571 | } 572 | list[idx] = *d 573 | } 574 | dest.%[2]s = list 575 | return nil 576 | }, 577 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 578 | if src == nil { 579 | return nil 580 | } 581 | list := make([]%[3]s, len(src.%[2]s)) 582 | for idx, obj := range src.%[2]s { 583 | d, err := obj.Convert() 584 | if err != nil { 585 | return err 586 | } 587 | list[idx] = *d 588 | } 589 | dest.%[2]s = list 590 | return nil 591 | }, 592 | }, 593 | `, st.Name(), field.Name, typeName, field.Tag.Name) 594 | } else if field.WithJWG() && field.IsPtr() { 595 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 596 | if err != nil { 597 | return err 598 | } 599 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 600 | fieldName: "%[2]s", 601 | jsonName: "%[4]s", 602 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 603 | if src == nil { 604 | return nil 605 | } else if src.%[2]s == nil { 606 | return nil 607 | } 608 | d, err := New%[3]sJSONBuilder().AddAll().Convert(src.%[2]s) 609 | if err != nil { 610 | return err 611 | } 612 | dest.%[2]s = d 613 | return nil 614 | }, 615 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 616 | if src == nil { 617 | return nil 618 | } else if src.%[2]s == nil { 619 | return nil 620 | } 621 | d, err := src.%[2]s.Convert() 622 | if err != nil { 623 | return err 624 | } 625 | dest.%[2]s = d 626 | return nil 627 | }, 628 | }, 629 | `, st.Name(), field.Name, typeName, field.Tag.Name) 630 | } else if field.WithJWG() { 631 | typeName, err := genbase.ExprToBaseTypeName(field.fieldInfo.Type) 632 | if err != nil { 633 | return err 634 | } 635 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 636 | fieldName: "%[2]s", 637 | jsonName: "%[4]s", 638 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 639 | if src == nil { 640 | return nil 641 | } 642 | d, err := New%[3]sJSONBuilder().AddAll().Convert(&src.%[2]s) 643 | if err != nil { 644 | return err 645 | } 646 | dest.%[2]s = *d 647 | return nil 648 | }, 649 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 650 | if src == nil { 651 | return nil 652 | } 653 | d, err := src.%[2]s.Convert() 654 | if err != nil { 655 | return err 656 | } 657 | dest.%[2]s = *d 658 | return nil 659 | }, 660 | }, 661 | `, st.Name(), field.Name, typeName, field.Tag.Name) 662 | } else { 663 | g.Printf(`%[2]s: &%[1]sPropertyInfo{ 664 | fieldName: "%[2]s", 665 | jsonName: "%[3]s", 666 | Encoder: func(src *%[1]s, dest *%[1]sJSON) error { 667 | if src == nil { 668 | return nil 669 | } 670 | dest.%[2]s = src.%[2]s 671 | return nil 672 | }, 673 | Decoder: func(src *%[1]sJSON, dest *%[1]s) error { 674 | if src == nil { 675 | return nil 676 | } 677 | dest.%[2]s = src.%[2]s 678 | return nil 679 | }, 680 | }, 681 | `, st.Name(), field.Name, field.Tag.Name) 682 | } 683 | } 684 | } 685 | g.Printf("}\n") 686 | for _, field := range st.Fields { 687 | if field.Tag.Ignore { 688 | continue 689 | } 690 | g.Printf("jb._structPropertyMap[\"%[1]s\"] = jb.%[1]s\n", field.Name) 691 | g.Printf("jb._jsonPropertyMap[\"%[2]s\"] = jb.%[1]s\n", field.Name, field.Tag.Name) 692 | } 693 | g.Printf("return jb") 694 | g.Printf("}\n\n") 695 | 696 | // generate Properties method 697 | g.Printf("// Properties returns all properties on %[1]sJSONBuilder.\n", st.Name()) 698 | g.Printf("func (b *%[1]sJSONBuilder) Properties() []*%[1]sPropertyInfo {\n", st.Name()) 699 | g.Printf("return []*%[1]sPropertyInfo {\n", st.Name()) 700 | for _, field := range st.Fields { 701 | if field.Tag.Ignore { 702 | continue 703 | } 704 | if field.Name != "" { 705 | g.Printf("b.%[1]s,\n", field.Name) 706 | } else { 707 | // TODO add support for embed other struct 708 | } 709 | } 710 | g.Printf("}\n}\n\n") 711 | 712 | // generate AddAll method 713 | g.Printf("// AddAll adds all property to %[1]sJSONBuilder.\n", st.Name()) 714 | g.Printf("func (b *%[1]sJSONBuilder) AddAll() *%[1]sJSONBuilder {\n", st.Name()) 715 | for _, field := range st.Fields { 716 | if field.Tag.Ignore { 717 | continue 718 | } 719 | if field.Name != "" { 720 | g.Printf("b._properties[\"%[1]s\"] = b.%[1]s\n", field.Name) 721 | } else { 722 | // TODO add support for embed other struct 723 | } 724 | } 725 | g.Printf("return b\n") 726 | g.Printf("}\n\n") 727 | 728 | // generate method for modifing and marshaling 729 | g.Printf(` 730 | // Add specified property to %[1]sJSONBuilder. 731 | func (b *%[1]sJSONBuilder) Add(infos ...*%[1]sPropertyInfo) *%[1]sJSONBuilder { 732 | for _, info := range infos { 733 | b._properties[info.fieldName] = info 734 | } 735 | return b 736 | } 737 | 738 | // AddByJSONNames add properties to %[1]sJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 739 | func (b *%[1]sJSONBuilder) AddByJSONNames(names ...string) *%[1]sJSONBuilder { 740 | for _, name := range names { 741 | info := b._jsonPropertyMap[name] 742 | if info == nil { 743 | continue 744 | } 745 | b._properties[info.fieldName] = info 746 | } 747 | return b 748 | } 749 | // AddByNames add properties to %[1]sJSONBuilder by struct property name. if name is not in the builder, it will ignore. 750 | func (b *%[1]sJSONBuilder) AddByNames(names ...string) *%[1]sJSONBuilder { 751 | for _, name := range names { 752 | info := b._structPropertyMap[name] 753 | if info == nil { 754 | continue 755 | } 756 | b._properties[info.fieldName] = info 757 | } 758 | return b 759 | } 760 | 761 | // Remove specified property to %[1]sJSONBuilder. 762 | func (b *%[1]sJSONBuilder) Remove(infos ...*%[1]sPropertyInfo) *%[1]sJSONBuilder { 763 | for _, info := range infos { 764 | delete(b._properties, info.fieldName) 765 | } 766 | return b 767 | } 768 | 769 | // RemoveByJSONNames remove properties to %[1]sJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 770 | func (b *%[1]sJSONBuilder) RemoveByJSONNames(names ...string) *%[1]sJSONBuilder { 771 | 772 | for _, name := range names { 773 | info := b._jsonPropertyMap[name] 774 | if info == nil { 775 | continue 776 | } 777 | delete(b._properties, info.fieldName) 778 | } 779 | return b 780 | } 781 | // RemoveByNames remove properties to %[1]sJSONBuilder by struct property name. if name is not in the builder, it will ignore. 782 | func (b *%[1]sJSONBuilder) RemoveByNames(names ...string) *%[1]sJSONBuilder { 783 | for _, name := range names { 784 | info := b._structPropertyMap[name] 785 | if info == nil { 786 | continue 787 | } 788 | delete(b._properties, info.fieldName) 789 | } 790 | return b 791 | } 792 | 793 | // Convert specified non-JSON object to JSON object. 794 | func (b *%[1]sJSONBuilder) Convert(orig *%[1]s) (*%[1]sJSON, error) { 795 | if orig == nil { 796 | return nil, nil 797 | } 798 | ret := &%[1]sJSON{} 799 | 800 | for _, info := range b._properties { 801 | if err := info.Encoder(orig, ret); err != nil { 802 | return nil, err 803 | } 804 | } 805 | 806 | return ret, nil 807 | } 808 | 809 | // ConvertList specified non-JSON slice to JSONList. 810 | func (b *%[1]sJSONBuilder) ConvertList(orig []*%[1]s) (%[1]sJSONList, error) { 811 | if orig == nil { 812 | return nil, nil 813 | } 814 | 815 | list := make(%[1]sJSONList, len(orig)) 816 | for idx, or := range orig { 817 | json, err := b.Convert(or) 818 | if err != nil { 819 | return nil, err 820 | } 821 | list[idx] = json 822 | } 823 | 824 | return list, nil 825 | } 826 | 827 | // Convert specified JSON object to non-JSON object. 828 | func (orig *%[1]sJSON) Convert() (*%[1]s, error) { 829 | ret := &%[1]s{} 830 | 831 | b := New%[1]sJSONBuilder().AddAll() 832 | for _, info := range b._properties { 833 | if err := info.Decoder(orig, ret); err != nil { 834 | return nil, err 835 | } 836 | } 837 | 838 | return ret, nil 839 | } 840 | 841 | // Convert specified JSONList to non-JSON slice. 842 | func (jsonList %[1]sJSONList) Convert() ([]*%[1]s, error) { 843 | orig := ([]*%[1]sJSON)(jsonList) 844 | 845 | list := make([]*%[1]s, len(orig)) 846 | for idx, or := range orig { 847 | obj, err := or.Convert() 848 | if err != nil { 849 | return nil, err 850 | } 851 | list[idx] = obj 852 | } 853 | 854 | return list, nil 855 | } 856 | 857 | // Marshal non-JSON object to JSON string. 858 | func (b *%[1]sJSONBuilder) Marshal(orig *%[1]s) ([]byte, error) { 859 | ret, err := b.Convert(orig) 860 | if err != nil { 861 | return nil, err 862 | } 863 | return json.Marshal(ret) 864 | } 865 | `, st.Name()) 866 | 867 | g.Printf("\n\n") 868 | 869 | return nil 870 | } 871 | 872 | // Name returns struct type name. 873 | func (st *BuildStruct) Name() string { 874 | return st.typeInfo.Name() 875 | } 876 | 877 | // WithJWG returns is field jwg annotated type. 878 | func (f *BuildField) WithJWG() bool { 879 | fieldType, err := genbase.ExprToBaseTypeName(f.fieldInfo.Type) 880 | if err != nil { 881 | panic(err) 882 | } 883 | for _, st := range f.parent.parent.Structs { 884 | if fieldType == st.Name() { 885 | return true 886 | } 887 | } 888 | return false 889 | } 890 | 891 | // IsPtr returns field type is pointer. 892 | func (f *BuildField) IsPtr() bool { 893 | return f.fieldInfo.IsPtr() 894 | } 895 | 896 | // IsArray returns field type is array. 897 | func (f *BuildField) IsArray() bool { 898 | return f.fieldInfo.IsArray() 899 | } 900 | 901 | // IsPtrArray returns field type is pointer array. 902 | func (f *BuildField) IsPtrArray() bool { 903 | return f.fieldInfo.IsPtrArray() 904 | } 905 | 906 | // IsArrayPtr returns field type is array of pointer. 907 | func (f *BuildField) IsArrayPtr() bool { 908 | return f.fieldInfo.IsArrayPtr() 909 | } 910 | 911 | // IsPtrArrayPtr returns field type is pointer of pointer array. 912 | func (f *BuildField) IsPtrArrayPtr() bool { 913 | return f.fieldInfo.IsPtrArrayPtr() 914 | } 915 | 916 | // TagString build tag string. 917 | func (tag *BuildTag) TagString() string { 918 | result := tag.Name 919 | if tag.isNoomitempty() { 920 | if tag.OmitEmpty { 921 | result += ",omitempty" 922 | } 923 | } else { 924 | if tag.OmitEmpty || !tag.ShouldEmit { 925 | result += ",omitempty" 926 | } 927 | } 928 | if tag.String { // TODO add special support for int64 929 | result += ",string" 930 | } 931 | return "json:\"" + result + "\"" 932 | } 933 | 934 | // isNoomitempty returns whether to suppress omitempty tag 935 | func (tag *BuildTag) isNoomitempty() bool { 936 | if tag.field.parent.parent.noOmitempty { 937 | return true 938 | } 939 | 940 | typeName, err := genbase.ExprToTypeName(tag.field.fieldInfo.Type) 941 | if err != nil { 942 | return false 943 | } 944 | 945 | for _, t := range tag.field.parent.parent.noOmitemptyFieldTypes { 946 | if t == typeName { 947 | return true 948 | } 949 | } 950 | 951 | return false 952 | } 953 | -------------------------------------------------------------------------------- /generator_test.go: -------------------------------------------------------------------------------- 1 | package jwg 2 | 3 | import ( 4 | "io/ioutil" 5 | "testing" 6 | 7 | "github.com/favclip/genbase" 8 | "github.com/pmezard/go-difflib/difflib" 9 | ) 10 | 11 | func TestGeneratorParsePackageDir(t *testing.T) { 12 | 13 | p := &genbase.Parser{} 14 | pInfo, err := p.ParsePackageDir("./misc/fixture/a") 15 | if err != nil { 16 | t.Log(err) 17 | t.Fail() 18 | } 19 | 20 | if pInfo.Name() != "a" { 21 | t.Log("package name is not a, actual", pInfo.Name()) 22 | t.Fail() 23 | } 24 | if len(pInfo.Files) != 2 { 25 | t.Log("package files length is not 2, actual", len(pInfo.Files)) 26 | t.Fail() 27 | } 28 | if pInfo.Dir != "./misc/fixture/a" { 29 | t.Log("package dir is not ./misc/fixture/a, actual", pInfo.Dir) 30 | t.Fail() 31 | } 32 | } 33 | 34 | func TestGeneratorParsePackageFiles(t *testing.T) { 35 | p := &genbase.Parser{} 36 | pInfo, err := p.ParsePackageFiles([]string{"./misc/fixture/a/model.go"}) 37 | if err != nil { 38 | t.Log(err) 39 | t.Fail() 40 | } 41 | 42 | if pInfo.Name() != "a" { 43 | t.Log("package name is not a, actual", pInfo.Name()) 44 | t.Fail() 45 | } 46 | if len(pInfo.Files) != 1 { 47 | t.Log("package files length is not 1, actual", len(pInfo.Files)) 48 | t.Fail() 49 | } 50 | if pInfo.Dir != "." { 51 | t.Log("package dir is not ., actual", pInfo.Dir) 52 | t.Fail() 53 | } 54 | } 55 | 56 | func TestGeneratorGenerate(t *testing.T) { 57 | 58 | specs := []struct { 59 | CaseName string 60 | Args []string 61 | TypeNames []string 62 | TranscriptTags []string 63 | NoOmitempty bool 64 | NoOmitemptyFieldTypes []string 65 | }{ 66 | { 67 | CaseName: "a", 68 | }, 69 | { 70 | CaseName: "b", 71 | }, 72 | { 73 | CaseName: "c", 74 | }, 75 | { 76 | CaseName: "g", 77 | Args: []string{"-type", "Sample,Inner", "-output", "misc/fixture/g/model_json.go", "misc/fixture/g"}, 78 | TypeNames: []string{"Sample", "Inner"}, 79 | }, 80 | { 81 | CaseName: "h", 82 | }, 83 | { 84 | CaseName: "l", 85 | Args: []string{"-type", "Sample", "-output", "misc/fixture/l/model_json.go", "-transcripttag", "swagger,includes", "misc/fixture/l"}, 86 | TypeNames: []string{"Sample"}, 87 | TranscriptTags: []string{"swagger", "includes"}, 88 | }, 89 | { 90 | CaseName: "n", 91 | Args: []string{"-type", "Sample", "-output", "misc/fixture/n/model_json.go", "-noOmitempty", "misc/fixture/n"}, 92 | TypeNames: []string{"Sample"}, 93 | NoOmitempty: true, 94 | }, 95 | { 96 | CaseName: "t", 97 | Args: []string{"-type", "Sample", "-output", "misc/fixture/t/model_json.go", "-noOmitemptyFieldType=bool,int", "misc/fixture/t"}, 98 | TypeNames: []string{"Sample"}, 99 | NoOmitemptyFieldTypes: []string{"bool", "int"}, 100 | }, 101 | } 102 | 103 | for _, spec := range specs { 104 | t.Run(spec.CaseName, func(t *testing.T) { 105 | p := &genbase.Parser{} 106 | pInfo, err := p.ParsePackageDir("./misc/fixture/" + spec.CaseName) 107 | if err != nil { 108 | t.Log(err) 109 | t.Fail() 110 | } 111 | if len(spec.Args) == 0 { 112 | spec.Args = []string{"-type", "Sample", "-output", "misc/fixture/" + spec.CaseName + "/model_json.go", "misc/fixture/" + spec.CaseName} 113 | } 114 | if len(spec.TypeNames) == 0 { 115 | spec.TypeNames = []string{"Sample"} 116 | } 117 | 118 | bu, err := Parse(pInfo, pInfo.CollectTypeInfos(spec.TypeNames), &ParseOptions{ 119 | TranscriptTagNames: spec.TranscriptTags, 120 | NoOmitempty: spec.NoOmitempty, 121 | NoOmitemptyFieldTypes: spec.NoOmitemptyFieldTypes, 122 | }) 123 | if err != nil { 124 | t.Log(err) 125 | t.Fail() 126 | } 127 | src, err := bu.Emit(&spec.Args) 128 | if err != nil { 129 | t.Log(err) 130 | t.Fail() 131 | } 132 | expected, err := ioutil.ReadFile("./misc/fixture/" + spec.CaseName + "/model_json.go") 133 | if err != nil { 134 | t.Log(err) 135 | t.Fail() 136 | } 137 | if string(src) != string(expected) { 138 | diff := difflib.UnifiedDiff{ 139 | A: difflib.SplitLines(string(expected)), 140 | B: difflib.SplitLines(string(src)), 141 | Context: 5, 142 | } 143 | d, err := difflib.GetUnifiedDiffString(diff) 144 | if err != nil { 145 | t.Fatal(err) 146 | } 147 | t.Fatal(d) 148 | } 149 | }) 150 | } 151 | } 152 | 153 | func TestCollectTaggedTypes(t *testing.T) { 154 | p := &genbase.Parser{} 155 | pInfo, err := p.ParsePackageFiles([]string{"./misc/fixture/d/model.go"}) 156 | if err != nil { 157 | t.Log(err) 158 | t.Fail() 159 | } 160 | 161 | names := pInfo.CollectTaggedTypeInfos("+jwg") 162 | if len(names) != 1 { 163 | t.Log("names length is not 1, actual", len(names)) 164 | t.Fail() 165 | } 166 | if names[0].Name() != "Sample" { 167 | t.Log("name[0] is not \"Sample\", actual", names[0].Name()) 168 | t.Fail() 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /misc/fixture/a/model.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | // test for basic struct definition 4 | 5 | type Sample struct { 6 | Foo string 7 | } 8 | -------------------------------------------------------------------------------- /misc/fixture/a/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/a/model_json.go misc/fixture/a; DO NOT EDIT 2 | 3 | package a 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | Foo string `json:"foo,omitempty"` 12 | } 13 | 14 | // SampleJSONList is synonym about []*SampleJSON. 15 | type SampleJSONList []*SampleJSON 16 | 17 | // SamplePropertyEncoder is property encoder for [1]sJSON. 18 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 19 | 20 | // SamplePropertyDecoder is property decoder for [1]sJSON. 21 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 22 | 23 | // SamplePropertyInfo stores property information. 24 | type SamplePropertyInfo struct { 25 | fieldName string 26 | jsonName string 27 | Encoder SamplePropertyEncoder 28 | Decoder SamplePropertyDecoder 29 | } 30 | 31 | // FieldName returns struct field name of property. 32 | func (info *SamplePropertyInfo) FieldName() string { 33 | return info.fieldName 34 | } 35 | 36 | // JSONName returns json field name of property. 37 | func (info *SamplePropertyInfo) JSONName() string { 38 | return info.jsonName 39 | } 40 | 41 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 42 | type SampleJSONBuilder struct { 43 | _properties map[string]*SamplePropertyInfo 44 | _jsonPropertyMap map[string]*SamplePropertyInfo 45 | _structPropertyMap map[string]*SamplePropertyInfo 46 | Foo *SamplePropertyInfo 47 | } 48 | 49 | // NewSampleJSONBuilder make new SampleJSONBuilder. 50 | func NewSampleJSONBuilder() *SampleJSONBuilder { 51 | jb := &SampleJSONBuilder{ 52 | _properties: map[string]*SamplePropertyInfo{}, 53 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 54 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 55 | Foo: &SamplePropertyInfo{ 56 | fieldName: "Foo", 57 | jsonName: "foo", 58 | Encoder: func(src *Sample, dest *SampleJSON) error { 59 | if src == nil { 60 | return nil 61 | } 62 | dest.Foo = src.Foo 63 | return nil 64 | }, 65 | Decoder: func(src *SampleJSON, dest *Sample) error { 66 | if src == nil { 67 | return nil 68 | } 69 | dest.Foo = src.Foo 70 | return nil 71 | }, 72 | }, 73 | } 74 | jb._structPropertyMap["Foo"] = jb.Foo 75 | jb._jsonPropertyMap["foo"] = jb.Foo 76 | return jb 77 | } 78 | 79 | // Properties returns all properties on SampleJSONBuilder. 80 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 81 | return []*SamplePropertyInfo{ 82 | b.Foo, 83 | } 84 | } 85 | 86 | // AddAll adds all property to SampleJSONBuilder. 87 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 88 | b._properties["Foo"] = b.Foo 89 | return b 90 | } 91 | 92 | // Add specified property to SampleJSONBuilder. 93 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 94 | for _, info := range infos { 95 | b._properties[info.fieldName] = info 96 | } 97 | return b 98 | } 99 | 100 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 101 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 102 | for _, name := range names { 103 | info := b._jsonPropertyMap[name] 104 | if info == nil { 105 | continue 106 | } 107 | b._properties[info.fieldName] = info 108 | } 109 | return b 110 | } 111 | 112 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 113 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 114 | for _, name := range names { 115 | info := b._structPropertyMap[name] 116 | if info == nil { 117 | continue 118 | } 119 | b._properties[info.fieldName] = info 120 | } 121 | return b 122 | } 123 | 124 | // Remove specified property to SampleJSONBuilder. 125 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 126 | for _, info := range infos { 127 | delete(b._properties, info.fieldName) 128 | } 129 | return b 130 | } 131 | 132 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 133 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 134 | 135 | for _, name := range names { 136 | info := b._jsonPropertyMap[name] 137 | if info == nil { 138 | continue 139 | } 140 | delete(b._properties, info.fieldName) 141 | } 142 | return b 143 | } 144 | 145 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 146 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 147 | for _, name := range names { 148 | info := b._structPropertyMap[name] 149 | if info == nil { 150 | continue 151 | } 152 | delete(b._properties, info.fieldName) 153 | } 154 | return b 155 | } 156 | 157 | // Convert specified non-JSON object to JSON object. 158 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 159 | if orig == nil { 160 | return nil, nil 161 | } 162 | ret := &SampleJSON{} 163 | 164 | for _, info := range b._properties { 165 | if err := info.Encoder(orig, ret); err != nil { 166 | return nil, err 167 | } 168 | } 169 | 170 | return ret, nil 171 | } 172 | 173 | // ConvertList specified non-JSON slice to JSONList. 174 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 175 | if orig == nil { 176 | return nil, nil 177 | } 178 | 179 | list := make(SampleJSONList, len(orig)) 180 | for idx, or := range orig { 181 | json, err := b.Convert(or) 182 | if err != nil { 183 | return nil, err 184 | } 185 | list[idx] = json 186 | } 187 | 188 | return list, nil 189 | } 190 | 191 | // Convert specified JSON object to non-JSON object. 192 | func (orig *SampleJSON) Convert() (*Sample, error) { 193 | ret := &Sample{} 194 | 195 | b := NewSampleJSONBuilder().AddAll() 196 | for _, info := range b._properties { 197 | if err := info.Decoder(orig, ret); err != nil { 198 | return nil, err 199 | } 200 | } 201 | 202 | return ret, nil 203 | } 204 | 205 | // Convert specified JSONList to non-JSON slice. 206 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 207 | orig := ([]*SampleJSON)(jsonList) 208 | 209 | list := make([]*Sample, len(orig)) 210 | for idx, or := range orig { 211 | obj, err := or.Convert() 212 | if err != nil { 213 | return nil, err 214 | } 215 | list[idx] = obj 216 | } 217 | 218 | return list, nil 219 | } 220 | 221 | // Marshal non-JSON object to JSON string. 222 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 223 | ret, err := b.Convert(orig) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return json.Marshal(ret) 228 | } 229 | -------------------------------------------------------------------------------- /misc/fixture/b/model.go: -------------------------------------------------------------------------------- 1 | package b 2 | 3 | // test for struct with json tags definition 4 | 5 | type Sample struct { 6 | A string `json:"foo!"` 7 | B string `json:",omitempty"` 8 | C int `json:",string"` 9 | D int `json:",omitempty,string"` 10 | E string `json:"-"` 11 | F int64 `` // add ,string automatically 12 | G []int64 `` // do not add ,string 13 | } 14 | -------------------------------------------------------------------------------- /misc/fixture/b/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/b/model_json.go misc/fixture/b; DO NOT EDIT 2 | 3 | package b 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"foo!,omitempty"` 12 | B string `json:"b,omitempty"` 13 | C int `json:"c,omitempty,string"` 14 | D int `json:"d,omitempty,string"` 15 | F int64 `json:"f,omitempty,string"` 16 | G []int64 `json:"g,omitempty"` 17 | } 18 | 19 | // SampleJSONList is synonym about []*SampleJSON. 20 | type SampleJSONList []*SampleJSON 21 | 22 | // SamplePropertyEncoder is property encoder for [1]sJSON. 23 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 24 | 25 | // SamplePropertyDecoder is property decoder for [1]sJSON. 26 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 27 | 28 | // SamplePropertyInfo stores property information. 29 | type SamplePropertyInfo struct { 30 | fieldName string 31 | jsonName string 32 | Encoder SamplePropertyEncoder 33 | Decoder SamplePropertyDecoder 34 | } 35 | 36 | // FieldName returns struct field name of property. 37 | func (info *SamplePropertyInfo) FieldName() string { 38 | return info.fieldName 39 | } 40 | 41 | // JSONName returns json field name of property. 42 | func (info *SamplePropertyInfo) JSONName() string { 43 | return info.jsonName 44 | } 45 | 46 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 47 | type SampleJSONBuilder struct { 48 | _properties map[string]*SamplePropertyInfo 49 | _jsonPropertyMap map[string]*SamplePropertyInfo 50 | _structPropertyMap map[string]*SamplePropertyInfo 51 | A *SamplePropertyInfo 52 | B *SamplePropertyInfo 53 | C *SamplePropertyInfo 54 | D *SamplePropertyInfo 55 | F *SamplePropertyInfo 56 | G *SamplePropertyInfo 57 | } 58 | 59 | // NewSampleJSONBuilder make new SampleJSONBuilder. 60 | func NewSampleJSONBuilder() *SampleJSONBuilder { 61 | jb := &SampleJSONBuilder{ 62 | _properties: map[string]*SamplePropertyInfo{}, 63 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 64 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 65 | A: &SamplePropertyInfo{ 66 | fieldName: "A", 67 | jsonName: "foo!", 68 | Encoder: func(src *Sample, dest *SampleJSON) error { 69 | if src == nil { 70 | return nil 71 | } 72 | dest.A = src.A 73 | return nil 74 | }, 75 | Decoder: func(src *SampleJSON, dest *Sample) error { 76 | if src == nil { 77 | return nil 78 | } 79 | dest.A = src.A 80 | return nil 81 | }, 82 | }, 83 | B: &SamplePropertyInfo{ 84 | fieldName: "B", 85 | jsonName: "b", 86 | Encoder: func(src *Sample, dest *SampleJSON) error { 87 | if src == nil { 88 | return nil 89 | } 90 | dest.B = src.B 91 | return nil 92 | }, 93 | Decoder: func(src *SampleJSON, dest *Sample) error { 94 | if src == nil { 95 | return nil 96 | } 97 | dest.B = src.B 98 | return nil 99 | }, 100 | }, 101 | C: &SamplePropertyInfo{ 102 | fieldName: "C", 103 | jsonName: "c", 104 | Encoder: func(src *Sample, dest *SampleJSON) error { 105 | if src == nil { 106 | return nil 107 | } 108 | dest.C = src.C 109 | return nil 110 | }, 111 | Decoder: func(src *SampleJSON, dest *Sample) error { 112 | if src == nil { 113 | return nil 114 | } 115 | dest.C = src.C 116 | return nil 117 | }, 118 | }, 119 | D: &SamplePropertyInfo{ 120 | fieldName: "D", 121 | jsonName: "d", 122 | Encoder: func(src *Sample, dest *SampleJSON) error { 123 | if src == nil { 124 | return nil 125 | } 126 | dest.D = src.D 127 | return nil 128 | }, 129 | Decoder: func(src *SampleJSON, dest *Sample) error { 130 | if src == nil { 131 | return nil 132 | } 133 | dest.D = src.D 134 | return nil 135 | }, 136 | }, 137 | F: &SamplePropertyInfo{ 138 | fieldName: "F", 139 | jsonName: "f", 140 | Encoder: func(src *Sample, dest *SampleJSON) error { 141 | if src == nil { 142 | return nil 143 | } 144 | dest.F = src.F 145 | return nil 146 | }, 147 | Decoder: func(src *SampleJSON, dest *Sample) error { 148 | if src == nil { 149 | return nil 150 | } 151 | dest.F = src.F 152 | return nil 153 | }, 154 | }, 155 | G: &SamplePropertyInfo{ 156 | fieldName: "G", 157 | jsonName: "g", 158 | Encoder: func(src *Sample, dest *SampleJSON) error { 159 | if src == nil { 160 | return nil 161 | } 162 | dest.G = src.G 163 | return nil 164 | }, 165 | Decoder: func(src *SampleJSON, dest *Sample) error { 166 | if src == nil { 167 | return nil 168 | } 169 | dest.G = src.G 170 | return nil 171 | }, 172 | }, 173 | } 174 | jb._structPropertyMap["A"] = jb.A 175 | jb._jsonPropertyMap["foo!"] = jb.A 176 | jb._structPropertyMap["B"] = jb.B 177 | jb._jsonPropertyMap["b"] = jb.B 178 | jb._structPropertyMap["C"] = jb.C 179 | jb._jsonPropertyMap["c"] = jb.C 180 | jb._structPropertyMap["D"] = jb.D 181 | jb._jsonPropertyMap["d"] = jb.D 182 | jb._structPropertyMap["F"] = jb.F 183 | jb._jsonPropertyMap["f"] = jb.F 184 | jb._structPropertyMap["G"] = jb.G 185 | jb._jsonPropertyMap["g"] = jb.G 186 | return jb 187 | } 188 | 189 | // Properties returns all properties on SampleJSONBuilder. 190 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 191 | return []*SamplePropertyInfo{ 192 | b.A, 193 | b.B, 194 | b.C, 195 | b.D, 196 | b.F, 197 | b.G, 198 | } 199 | } 200 | 201 | // AddAll adds all property to SampleJSONBuilder. 202 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 203 | b._properties["A"] = b.A 204 | b._properties["B"] = b.B 205 | b._properties["C"] = b.C 206 | b._properties["D"] = b.D 207 | b._properties["F"] = b.F 208 | b._properties["G"] = b.G 209 | return b 210 | } 211 | 212 | // Add specified property to SampleJSONBuilder. 213 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 214 | for _, info := range infos { 215 | b._properties[info.fieldName] = info 216 | } 217 | return b 218 | } 219 | 220 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 221 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 222 | for _, name := range names { 223 | info := b._jsonPropertyMap[name] 224 | if info == nil { 225 | continue 226 | } 227 | b._properties[info.fieldName] = info 228 | } 229 | return b 230 | } 231 | 232 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 233 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 234 | for _, name := range names { 235 | info := b._structPropertyMap[name] 236 | if info == nil { 237 | continue 238 | } 239 | b._properties[info.fieldName] = info 240 | } 241 | return b 242 | } 243 | 244 | // Remove specified property to SampleJSONBuilder. 245 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 246 | for _, info := range infos { 247 | delete(b._properties, info.fieldName) 248 | } 249 | return b 250 | } 251 | 252 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 253 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 254 | 255 | for _, name := range names { 256 | info := b._jsonPropertyMap[name] 257 | if info == nil { 258 | continue 259 | } 260 | delete(b._properties, info.fieldName) 261 | } 262 | return b 263 | } 264 | 265 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 266 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 267 | for _, name := range names { 268 | info := b._structPropertyMap[name] 269 | if info == nil { 270 | continue 271 | } 272 | delete(b._properties, info.fieldName) 273 | } 274 | return b 275 | } 276 | 277 | // Convert specified non-JSON object to JSON object. 278 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 279 | if orig == nil { 280 | return nil, nil 281 | } 282 | ret := &SampleJSON{} 283 | 284 | for _, info := range b._properties { 285 | if err := info.Encoder(orig, ret); err != nil { 286 | return nil, err 287 | } 288 | } 289 | 290 | return ret, nil 291 | } 292 | 293 | // ConvertList specified non-JSON slice to JSONList. 294 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 295 | if orig == nil { 296 | return nil, nil 297 | } 298 | 299 | list := make(SampleJSONList, len(orig)) 300 | for idx, or := range orig { 301 | json, err := b.Convert(or) 302 | if err != nil { 303 | return nil, err 304 | } 305 | list[idx] = json 306 | } 307 | 308 | return list, nil 309 | } 310 | 311 | // Convert specified JSON object to non-JSON object. 312 | func (orig *SampleJSON) Convert() (*Sample, error) { 313 | ret := &Sample{} 314 | 315 | b := NewSampleJSONBuilder().AddAll() 316 | for _, info := range b._properties { 317 | if err := info.Decoder(orig, ret); err != nil { 318 | return nil, err 319 | } 320 | } 321 | 322 | return ret, nil 323 | } 324 | 325 | // Convert specified JSONList to non-JSON slice. 326 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 327 | orig := ([]*SampleJSON)(jsonList) 328 | 329 | list := make([]*Sample, len(orig)) 330 | for idx, or := range orig { 331 | obj, err := or.Convert() 332 | if err != nil { 333 | return nil, err 334 | } 335 | list[idx] = obj 336 | } 337 | 338 | return list, nil 339 | } 340 | 341 | // Marshal non-JSON object to JSON string. 342 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 343 | ret, err := b.Convert(orig) 344 | if err != nil { 345 | return nil, err 346 | } 347 | return json.Marshal(ret) 348 | } 349 | -------------------------------------------------------------------------------- /misc/fixture/c/model.go: -------------------------------------------------------------------------------- 1 | package c 2 | 3 | // test for struct with json tag and another tags definition 4 | 5 | type Sample struct { 6 | A string `json:"foo!" datastore:"-"` 7 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 8 | } 9 | -------------------------------------------------------------------------------- /misc/fixture/c/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/c/model_json.go misc/fixture/c; DO NOT EDIT 2 | 3 | package c 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"foo!,omitempty"` 12 | B string `json:"b,omitempty"` 13 | } 14 | 15 | // SampleJSONList is synonym about []*SampleJSON. 16 | type SampleJSONList []*SampleJSON 17 | 18 | // SamplePropertyEncoder is property encoder for [1]sJSON. 19 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 20 | 21 | // SamplePropertyDecoder is property decoder for [1]sJSON. 22 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 23 | 24 | // SamplePropertyInfo stores property information. 25 | type SamplePropertyInfo struct { 26 | fieldName string 27 | jsonName string 28 | Encoder SamplePropertyEncoder 29 | Decoder SamplePropertyDecoder 30 | } 31 | 32 | // FieldName returns struct field name of property. 33 | func (info *SamplePropertyInfo) FieldName() string { 34 | return info.fieldName 35 | } 36 | 37 | // JSONName returns json field name of property. 38 | func (info *SamplePropertyInfo) JSONName() string { 39 | return info.jsonName 40 | } 41 | 42 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 43 | type SampleJSONBuilder struct { 44 | _properties map[string]*SamplePropertyInfo 45 | _jsonPropertyMap map[string]*SamplePropertyInfo 46 | _structPropertyMap map[string]*SamplePropertyInfo 47 | A *SamplePropertyInfo 48 | B *SamplePropertyInfo 49 | } 50 | 51 | // NewSampleJSONBuilder make new SampleJSONBuilder. 52 | func NewSampleJSONBuilder() *SampleJSONBuilder { 53 | jb := &SampleJSONBuilder{ 54 | _properties: map[string]*SamplePropertyInfo{}, 55 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 56 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 57 | A: &SamplePropertyInfo{ 58 | fieldName: "A", 59 | jsonName: "foo!", 60 | Encoder: func(src *Sample, dest *SampleJSON) error { 61 | if src == nil { 62 | return nil 63 | } 64 | dest.A = src.A 65 | return nil 66 | }, 67 | Decoder: func(src *SampleJSON, dest *Sample) error { 68 | if src == nil { 69 | return nil 70 | } 71 | dest.A = src.A 72 | return nil 73 | }, 74 | }, 75 | B: &SamplePropertyInfo{ 76 | fieldName: "B", 77 | jsonName: "b", 78 | Encoder: func(src *Sample, dest *SampleJSON) error { 79 | if src == nil { 80 | return nil 81 | } 82 | dest.B = src.B 83 | return nil 84 | }, 85 | Decoder: func(src *SampleJSON, dest *Sample) error { 86 | if src == nil { 87 | return nil 88 | } 89 | dest.B = src.B 90 | return nil 91 | }, 92 | }, 93 | } 94 | jb._structPropertyMap["A"] = jb.A 95 | jb._jsonPropertyMap["foo!"] = jb.A 96 | jb._structPropertyMap["B"] = jb.B 97 | jb._jsonPropertyMap["b"] = jb.B 98 | return jb 99 | } 100 | 101 | // Properties returns all properties on SampleJSONBuilder. 102 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 103 | return []*SamplePropertyInfo{ 104 | b.A, 105 | b.B, 106 | } 107 | } 108 | 109 | // AddAll adds all property to SampleJSONBuilder. 110 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 111 | b._properties["A"] = b.A 112 | b._properties["B"] = b.B 113 | return b 114 | } 115 | 116 | // Add specified property to SampleJSONBuilder. 117 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 118 | for _, info := range infos { 119 | b._properties[info.fieldName] = info 120 | } 121 | return b 122 | } 123 | 124 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 125 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 126 | for _, name := range names { 127 | info := b._jsonPropertyMap[name] 128 | if info == nil { 129 | continue 130 | } 131 | b._properties[info.fieldName] = info 132 | } 133 | return b 134 | } 135 | 136 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 137 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 138 | for _, name := range names { 139 | info := b._structPropertyMap[name] 140 | if info == nil { 141 | continue 142 | } 143 | b._properties[info.fieldName] = info 144 | } 145 | return b 146 | } 147 | 148 | // Remove specified property to SampleJSONBuilder. 149 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 150 | for _, info := range infos { 151 | delete(b._properties, info.fieldName) 152 | } 153 | return b 154 | } 155 | 156 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 157 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 158 | 159 | for _, name := range names { 160 | info := b._jsonPropertyMap[name] 161 | if info == nil { 162 | continue 163 | } 164 | delete(b._properties, info.fieldName) 165 | } 166 | return b 167 | } 168 | 169 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 170 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 171 | for _, name := range names { 172 | info := b._structPropertyMap[name] 173 | if info == nil { 174 | continue 175 | } 176 | delete(b._properties, info.fieldName) 177 | } 178 | return b 179 | } 180 | 181 | // Convert specified non-JSON object to JSON object. 182 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 183 | if orig == nil { 184 | return nil, nil 185 | } 186 | ret := &SampleJSON{} 187 | 188 | for _, info := range b._properties { 189 | if err := info.Encoder(orig, ret); err != nil { 190 | return nil, err 191 | } 192 | } 193 | 194 | return ret, nil 195 | } 196 | 197 | // ConvertList specified non-JSON slice to JSONList. 198 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 199 | if orig == nil { 200 | return nil, nil 201 | } 202 | 203 | list := make(SampleJSONList, len(orig)) 204 | for idx, or := range orig { 205 | json, err := b.Convert(or) 206 | if err != nil { 207 | return nil, err 208 | } 209 | list[idx] = json 210 | } 211 | 212 | return list, nil 213 | } 214 | 215 | // Convert specified JSON object to non-JSON object. 216 | func (orig *SampleJSON) Convert() (*Sample, error) { 217 | ret := &Sample{} 218 | 219 | b := NewSampleJSONBuilder().AddAll() 220 | for _, info := range b._properties { 221 | if err := info.Decoder(orig, ret); err != nil { 222 | return nil, err 223 | } 224 | } 225 | 226 | return ret, nil 227 | } 228 | 229 | // Convert specified JSONList to non-JSON slice. 230 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 231 | orig := ([]*SampleJSON)(jsonList) 232 | 233 | list := make([]*Sample, len(orig)) 234 | for idx, or := range orig { 235 | obj, err := or.Convert() 236 | if err != nil { 237 | return nil, err 238 | } 239 | list[idx] = obj 240 | } 241 | 242 | return list, nil 243 | } 244 | 245 | // Marshal non-JSON object to JSON string. 246 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 247 | ret, err := b.Convert(orig) 248 | if err != nil { 249 | return nil, err 250 | } 251 | return json.Marshal(ret) 252 | } 253 | -------------------------------------------------------------------------------- /misc/fixture/d/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -output model_json.go . 2 | 3 | package d 4 | 5 | // test for struct with tagged comment 6 | 7 | // +jwg 8 | type Sample struct { 9 | A string `json:"foo!" datastore:"-"` 10 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 11 | } 12 | 13 | type IgnoredSample struct { 14 | A string `json:"foo!" datastore:"-"` 15 | B string `json:",omitempty" datastore:",noindex" endpoints:"req"` 16 | } 17 | -------------------------------------------------------------------------------- /misc/fixture/d/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -output misc/fixture/d/model_json.go misc/fixture/d; DO NOT EDIT 2 | 3 | package d 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"foo!,omitempty"` 12 | B string `json:"b,omitempty"` 13 | } 14 | 15 | // SampleJSONList is synonym about []*SampleJSON. 16 | type SampleJSONList []*SampleJSON 17 | 18 | // SamplePropertyEncoder is property encoder for [1]sJSON. 19 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 20 | 21 | // SamplePropertyDecoder is property decoder for [1]sJSON. 22 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 23 | 24 | // SamplePropertyInfo stores property information. 25 | type SamplePropertyInfo struct { 26 | fieldName string 27 | jsonName string 28 | Encoder SamplePropertyEncoder 29 | Decoder SamplePropertyDecoder 30 | } 31 | 32 | // FieldName returns struct field name of property. 33 | func (info *SamplePropertyInfo) FieldName() string { 34 | return info.fieldName 35 | } 36 | 37 | // JSONName returns json field name of property. 38 | func (info *SamplePropertyInfo) JSONName() string { 39 | return info.jsonName 40 | } 41 | 42 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 43 | type SampleJSONBuilder struct { 44 | _properties map[string]*SamplePropertyInfo 45 | _jsonPropertyMap map[string]*SamplePropertyInfo 46 | _structPropertyMap map[string]*SamplePropertyInfo 47 | A *SamplePropertyInfo 48 | B *SamplePropertyInfo 49 | } 50 | 51 | // NewSampleJSONBuilder make new SampleJSONBuilder. 52 | func NewSampleJSONBuilder() *SampleJSONBuilder { 53 | jb := &SampleJSONBuilder{ 54 | _properties: map[string]*SamplePropertyInfo{}, 55 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 56 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 57 | A: &SamplePropertyInfo{ 58 | fieldName: "A", 59 | jsonName: "foo!", 60 | Encoder: func(src *Sample, dest *SampleJSON) error { 61 | if src == nil { 62 | return nil 63 | } 64 | dest.A = src.A 65 | return nil 66 | }, 67 | Decoder: func(src *SampleJSON, dest *Sample) error { 68 | if src == nil { 69 | return nil 70 | } 71 | dest.A = src.A 72 | return nil 73 | }, 74 | }, 75 | B: &SamplePropertyInfo{ 76 | fieldName: "B", 77 | jsonName: "b", 78 | Encoder: func(src *Sample, dest *SampleJSON) error { 79 | if src == nil { 80 | return nil 81 | } 82 | dest.B = src.B 83 | return nil 84 | }, 85 | Decoder: func(src *SampleJSON, dest *Sample) error { 86 | if src == nil { 87 | return nil 88 | } 89 | dest.B = src.B 90 | return nil 91 | }, 92 | }, 93 | } 94 | jb._structPropertyMap["A"] = jb.A 95 | jb._jsonPropertyMap["foo!"] = jb.A 96 | jb._structPropertyMap["B"] = jb.B 97 | jb._jsonPropertyMap["b"] = jb.B 98 | return jb 99 | } 100 | 101 | // Properties returns all properties on SampleJSONBuilder. 102 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 103 | return []*SamplePropertyInfo{ 104 | b.A, 105 | b.B, 106 | } 107 | } 108 | 109 | // AddAll adds all property to SampleJSONBuilder. 110 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 111 | b._properties["A"] = b.A 112 | b._properties["B"] = b.B 113 | return b 114 | } 115 | 116 | // Add specified property to SampleJSONBuilder. 117 | func (b *SampleJSONBuilder) Add(info *SamplePropertyInfo) *SampleJSONBuilder { 118 | b._properties[info.fieldName] = info 119 | return b 120 | } 121 | 122 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 123 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 124 | for _, name := range names { 125 | info := b._jsonPropertyMap[name] 126 | if info == nil { 127 | continue 128 | } 129 | b._properties[info.fieldName] = info 130 | } 131 | return b 132 | } 133 | 134 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 135 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 136 | for _, name := range names { 137 | info := b._structPropertyMap[name] 138 | if info == nil { 139 | continue 140 | } 141 | b._properties[info.fieldName] = info 142 | } 143 | return b 144 | } 145 | 146 | // Remove specified property to SampleJSONBuilder. 147 | func (b *SampleJSONBuilder) Remove(info *SamplePropertyInfo) *SampleJSONBuilder { 148 | delete(b._properties, info.fieldName) 149 | return b 150 | } 151 | 152 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 153 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 154 | 155 | for _, name := range names { 156 | info := b._jsonPropertyMap[name] 157 | if info == nil { 158 | continue 159 | } 160 | delete(b._properties, info.fieldName) 161 | } 162 | return b 163 | } 164 | 165 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 166 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 167 | for _, name := range names { 168 | info := b._structPropertyMap[name] 169 | if info == nil { 170 | continue 171 | } 172 | delete(b._properties, info.fieldName) 173 | } 174 | return b 175 | } 176 | 177 | // Convert specified non-JSON object to JSON object. 178 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 179 | if orig == nil { 180 | return nil, nil 181 | } 182 | ret := &SampleJSON{} 183 | 184 | for _, info := range b._properties { 185 | if err := info.Encoder(orig, ret); err != nil { 186 | return nil, err 187 | } 188 | } 189 | 190 | return ret, nil 191 | } 192 | 193 | // ConvertList specified non-JSON slice to JSONList. 194 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 195 | if orig == nil { 196 | return nil, nil 197 | } 198 | 199 | list := make(SampleJSONList, len(orig)) 200 | for idx, or := range orig { 201 | json, err := b.Convert(or) 202 | if err != nil { 203 | return nil, err 204 | } 205 | list[idx] = json 206 | } 207 | 208 | return list, nil 209 | } 210 | 211 | // Convert specified JSON object to non-JSON object. 212 | func (orig *SampleJSON) Convert() (*Sample, error) { 213 | ret := &Sample{} 214 | 215 | b := NewSampleJSONBuilder().AddAll() 216 | for _, info := range b._properties { 217 | if err := info.Decoder(orig, ret); err != nil { 218 | return nil, err 219 | } 220 | } 221 | 222 | return ret, nil 223 | } 224 | 225 | // Convert specified JSONList to non-JSON slice. 226 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 227 | orig := ([]*SampleJSON)(jsonList) 228 | 229 | list := make([]*Sample, len(orig)) 230 | for idx, or := range orig { 231 | obj, err := or.Convert() 232 | if err != nil { 233 | return nil, err 234 | } 235 | list[idx] = obj 236 | } 237 | 238 | return list, nil 239 | } 240 | 241 | // Marshal non-JSON object to JSON string. 242 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 243 | ret, err := b.Convert(orig) 244 | if err != nil { 245 | return nil, err 246 | } 247 | return json.Marshal(ret) 248 | } 249 | -------------------------------------------------------------------------------- /misc/fixture/e/model.go: -------------------------------------------------------------------------------- 1 | package e 2 | 3 | // test for pointer 4 | 5 | type Sample struct { 6 | Str *string 7 | Foo *Foo 8 | } 9 | 10 | type Foo struct { 11 | } 12 | -------------------------------------------------------------------------------- /misc/fixture/e/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/e/model_json.go misc/fixture/e; DO NOT EDIT 2 | 3 | package e 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | Str *string `json:"str,omitempty"` 12 | Foo *Foo `json:"foo,omitempty"` 13 | } 14 | 15 | // SampleJSONList is synonym about []*SampleJSON. 16 | type SampleJSONList []*SampleJSON 17 | 18 | // SamplePropertyEncoder is property encoder for [1]sJSON. 19 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 20 | 21 | // SamplePropertyDecoder is property decoder for [1]sJSON. 22 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 23 | 24 | // SamplePropertyInfo stores property information. 25 | type SamplePropertyInfo struct { 26 | fieldName string 27 | jsonName string 28 | Encoder SamplePropertyEncoder 29 | Decoder SamplePropertyDecoder 30 | } 31 | 32 | // FieldName returns struct field name of property. 33 | func (info *SamplePropertyInfo) FieldName() string { 34 | return info.fieldName 35 | } 36 | 37 | // JSONName returns json field name of property. 38 | func (info *SamplePropertyInfo) JSONName() string { 39 | return info.jsonName 40 | } 41 | 42 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 43 | type SampleJSONBuilder struct { 44 | _properties map[string]*SamplePropertyInfo 45 | _jsonPropertyMap map[string]*SamplePropertyInfo 46 | _structPropertyMap map[string]*SamplePropertyInfo 47 | Str *SamplePropertyInfo 48 | Foo *SamplePropertyInfo 49 | } 50 | 51 | // NewSampleJSONBuilder make new SampleJSONBuilder. 52 | func NewSampleJSONBuilder() *SampleJSONBuilder { 53 | jb := &SampleJSONBuilder{ 54 | _properties: map[string]*SamplePropertyInfo{}, 55 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 56 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 57 | Str: &SamplePropertyInfo{ 58 | fieldName: "Str", 59 | jsonName: "str", 60 | Encoder: func(src *Sample, dest *SampleJSON) error { 61 | if src == nil { 62 | return nil 63 | } 64 | dest.Str = src.Str 65 | return nil 66 | }, 67 | Decoder: func(src *SampleJSON, dest *Sample) error { 68 | if src == nil { 69 | return nil 70 | } 71 | dest.Str = src.Str 72 | return nil 73 | }, 74 | }, 75 | Foo: &SamplePropertyInfo{ 76 | fieldName: "Foo", 77 | jsonName: "foo", 78 | Encoder: func(src *Sample, dest *SampleJSON) error { 79 | if src == nil { 80 | return nil 81 | } 82 | dest.Foo = src.Foo 83 | return nil 84 | }, 85 | Decoder: func(src *SampleJSON, dest *Sample) error { 86 | if src == nil { 87 | return nil 88 | } 89 | dest.Foo = src.Foo 90 | return nil 91 | }, 92 | }, 93 | } 94 | jb._structPropertyMap["Str"] = jb.Str 95 | jb._jsonPropertyMap["str"] = jb.Str 96 | jb._structPropertyMap["Foo"] = jb.Foo 97 | jb._jsonPropertyMap["foo"] = jb.Foo 98 | return jb 99 | } 100 | 101 | // Properties returns all properties on SampleJSONBuilder. 102 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 103 | return []*SamplePropertyInfo{ 104 | b.Str, 105 | b.Foo, 106 | } 107 | } 108 | 109 | // AddAll adds all property to SampleJSONBuilder. 110 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 111 | b._properties["Str"] = b.Str 112 | b._properties["Foo"] = b.Foo 113 | return b 114 | } 115 | 116 | // Add specified property to SampleJSONBuilder. 117 | func (b *SampleJSONBuilder) Add(info *SamplePropertyInfo) *SampleJSONBuilder { 118 | b._properties[info.fieldName] = info 119 | return b 120 | } 121 | 122 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 123 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 124 | for _, name := range names { 125 | info := b._jsonPropertyMap[name] 126 | if info == nil { 127 | continue 128 | } 129 | b._properties[info.fieldName] = info 130 | } 131 | return b 132 | } 133 | 134 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 135 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 136 | for _, name := range names { 137 | info := b._structPropertyMap[name] 138 | if info == nil { 139 | continue 140 | } 141 | b._properties[info.fieldName] = info 142 | } 143 | return b 144 | } 145 | 146 | // Remove specified property to SampleJSONBuilder. 147 | func (b *SampleJSONBuilder) Remove(info *SamplePropertyInfo) *SampleJSONBuilder { 148 | delete(b._properties, info.fieldName) 149 | return b 150 | } 151 | 152 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 153 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 154 | 155 | for _, name := range names { 156 | info := b._jsonPropertyMap[name] 157 | if info == nil { 158 | continue 159 | } 160 | delete(b._properties, info.fieldName) 161 | } 162 | return b 163 | } 164 | 165 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 166 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 167 | for _, name := range names { 168 | info := b._structPropertyMap[name] 169 | if info == nil { 170 | continue 171 | } 172 | delete(b._properties, info.fieldName) 173 | } 174 | return b 175 | } 176 | 177 | // Convert specified non-JSON object to JSON object. 178 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 179 | if orig == nil { 180 | return nil, nil 181 | } 182 | ret := &SampleJSON{} 183 | 184 | for _, info := range b._properties { 185 | if err := info.Encoder(orig, ret); err != nil { 186 | return nil, err 187 | } 188 | } 189 | 190 | return ret, nil 191 | } 192 | 193 | // ConvertList specified non-JSON slice to JSONList. 194 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 195 | if orig == nil { 196 | return nil, nil 197 | } 198 | 199 | list := make(SampleJSONList, len(orig)) 200 | for idx, or := range orig { 201 | json, err := b.Convert(or) 202 | if err != nil { 203 | return nil, err 204 | } 205 | list[idx] = json 206 | } 207 | 208 | return list, nil 209 | } 210 | 211 | // Convert specified JSON object to non-JSON object. 212 | func (orig *SampleJSON) Convert() (*Sample, error) { 213 | ret := &Sample{} 214 | 215 | b := NewSampleJSONBuilder().AddAll() 216 | for _, info := range b._properties { 217 | if err := info.Decoder(orig, ret); err != nil { 218 | return nil, err 219 | } 220 | } 221 | 222 | return ret, nil 223 | } 224 | 225 | // Convert specified JSONList to non-JSON slice. 226 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 227 | orig := ([]*SampleJSON)(jsonList) 228 | 229 | list := make([]*Sample, len(orig)) 230 | for idx, or := range orig { 231 | obj, err := or.Convert() 232 | if err != nil { 233 | return nil, err 234 | } 235 | list[idx] = obj 236 | } 237 | 238 | return list, nil 239 | } 240 | 241 | // Marshal non-JSON object to JSON string. 242 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 243 | ret, err := b.Convert(orig) 244 | if err != nil { 245 | return nil, err 246 | } 247 | return json.Marshal(ret) 248 | } 249 | -------------------------------------------------------------------------------- /misc/fixture/f/model.go: -------------------------------------------------------------------------------- 1 | package f 2 | 3 | // test for import statement support 4 | 5 | import ( 6 | "github.com/favclip/jwg/misc/fixture/a" 7 | bravo "github.com/favclip/jwg/misc/fixture/b" 8 | // . "github.com/favclip/jwg/misc/fixture/c" // unsupported! 9 | ) 10 | 11 | type SampleF struct { 12 | A *a.Sample 13 | B *bravo.Sample 14 | // C *Sample 15 | } 16 | -------------------------------------------------------------------------------- /misc/fixture/f/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type SampleF -output misc/fixture/f/model_json.go misc/fixture/f; DO NOT EDIT 2 | 3 | package f 4 | 5 | import ( 6 | "encoding/json" 7 | "github.com/favclip/jwg/misc/fixture/a" 8 | bravo "github.com/favclip/jwg/misc/fixture/b" 9 | ) 10 | 11 | // SampleFJSON is jsonized struct for SampleF. 12 | type SampleFJSON struct { 13 | A *a.Sample `json:"a,omitempty"` 14 | B *bravo.Sample `json:"b,omitempty"` 15 | } 16 | 17 | // SampleFJSONList is synonym about []*SampleFJSON. 18 | type SampleFJSONList []*SampleFJSON 19 | 20 | // SampleFPropertyEncoder is property encoder for [1]sJSON. 21 | type SampleFPropertyEncoder func(src *SampleF, dest *SampleFJSON) error 22 | 23 | // SampleFPropertyDecoder is property decoder for [1]sJSON. 24 | type SampleFPropertyDecoder func(src *SampleFJSON, dest *SampleF) error 25 | 26 | // SampleFPropertyInfo stores property information. 27 | type SampleFPropertyInfo struct { 28 | fieldName string 29 | jsonName string 30 | Encoder SampleFPropertyEncoder 31 | Decoder SampleFPropertyDecoder 32 | } 33 | 34 | // FieldName returns struct field name of property. 35 | func (info *SampleFPropertyInfo) FieldName() string { 36 | return info.fieldName 37 | } 38 | 39 | // JSONName returns json field name of property. 40 | func (info *SampleFPropertyInfo) JSONName() string { 41 | return info.jsonName 42 | } 43 | 44 | // SampleFJSONBuilder convert between SampleF to SampleFJSON mutually. 45 | type SampleFJSONBuilder struct { 46 | _properties map[string]*SampleFPropertyInfo 47 | _jsonPropertyMap map[string]*SampleFPropertyInfo 48 | _structPropertyMap map[string]*SampleFPropertyInfo 49 | A *SampleFPropertyInfo 50 | B *SampleFPropertyInfo 51 | } 52 | 53 | // NewSampleFJSONBuilder make new SampleFJSONBuilder. 54 | func NewSampleFJSONBuilder() *SampleFJSONBuilder { 55 | jb := &SampleFJSONBuilder{ 56 | _properties: map[string]*SampleFPropertyInfo{}, 57 | _jsonPropertyMap: map[string]*SampleFPropertyInfo{}, 58 | _structPropertyMap: map[string]*SampleFPropertyInfo{}, 59 | A: &SampleFPropertyInfo{ 60 | fieldName: "A", 61 | jsonName: "a", 62 | Encoder: func(src *SampleF, dest *SampleFJSON) error { 63 | if src == nil { 64 | return nil 65 | } 66 | dest.A = src.A 67 | return nil 68 | }, 69 | Decoder: func(src *SampleFJSON, dest *SampleF) error { 70 | if src == nil { 71 | return nil 72 | } 73 | dest.A = src.A 74 | return nil 75 | }, 76 | }, 77 | B: &SampleFPropertyInfo{ 78 | fieldName: "B", 79 | jsonName: "b", 80 | Encoder: func(src *SampleF, dest *SampleFJSON) error { 81 | if src == nil { 82 | return nil 83 | } 84 | dest.B = src.B 85 | return nil 86 | }, 87 | Decoder: func(src *SampleFJSON, dest *SampleF) error { 88 | if src == nil { 89 | return nil 90 | } 91 | dest.B = src.B 92 | return nil 93 | }, 94 | }, 95 | } 96 | jb._structPropertyMap["A"] = jb.A 97 | jb._jsonPropertyMap["a"] = jb.A 98 | jb._structPropertyMap["B"] = jb.B 99 | jb._jsonPropertyMap["b"] = jb.B 100 | return jb 101 | } 102 | 103 | // Properties returns all properties on SampleFJSONBuilder. 104 | func (b *SampleFJSONBuilder) Properties() []*SampleFPropertyInfo { 105 | return []*SampleFPropertyInfo{ 106 | b.A, 107 | b.B, 108 | } 109 | } 110 | 111 | // AddAll adds all property to SampleFJSONBuilder. 112 | func (b *SampleFJSONBuilder) AddAll() *SampleFJSONBuilder { 113 | b._properties["A"] = b.A 114 | b._properties["B"] = b.B 115 | return b 116 | } 117 | 118 | // Add specified property to SampleFJSONBuilder. 119 | func (b *SampleFJSONBuilder) Add(info *SampleFPropertyInfo) *SampleFJSONBuilder { 120 | b._properties[info.fieldName] = info 121 | return b 122 | } 123 | 124 | // AddByJSONNames add properties to SampleFJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 125 | func (b *SampleFJSONBuilder) AddByJSONNames(names ...string) *SampleFJSONBuilder { 126 | for _, name := range names { 127 | info := b._jsonPropertyMap[name] 128 | if info == nil { 129 | continue 130 | } 131 | b._properties[info.fieldName] = info 132 | } 133 | return b 134 | } 135 | 136 | // AddByNames add properties to SampleFJSONBuilder by struct property name. if name is not in the builder, it will ignore. 137 | func (b *SampleFJSONBuilder) AddByNames(names ...string) *SampleFJSONBuilder { 138 | for _, name := range names { 139 | info := b._structPropertyMap[name] 140 | if info == nil { 141 | continue 142 | } 143 | b._properties[info.fieldName] = info 144 | } 145 | return b 146 | } 147 | 148 | // Remove specified property to SampleFJSONBuilder. 149 | func (b *SampleFJSONBuilder) Remove(info *SampleFPropertyInfo) *SampleFJSONBuilder { 150 | delete(b._properties, info.fieldName) 151 | return b 152 | } 153 | 154 | // RemoveByJSONNames remove properties to SampleFJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 155 | func (b *SampleFJSONBuilder) RemoveByJSONNames(names ...string) *SampleFJSONBuilder { 156 | 157 | for _, name := range names { 158 | info := b._jsonPropertyMap[name] 159 | if info == nil { 160 | continue 161 | } 162 | delete(b._properties, info.fieldName) 163 | } 164 | return b 165 | } 166 | 167 | // RemoveByNames remove properties to SampleFJSONBuilder by struct property name. if name is not in the builder, it will ignore. 168 | func (b *SampleFJSONBuilder) RemoveByNames(names ...string) *SampleFJSONBuilder { 169 | for _, name := range names { 170 | info := b._structPropertyMap[name] 171 | if info == nil { 172 | continue 173 | } 174 | delete(b._properties, info.fieldName) 175 | } 176 | return b 177 | } 178 | 179 | // Convert specified non-JSON object to JSON object. 180 | func (b *SampleFJSONBuilder) Convert(orig *SampleF) (*SampleFJSON, error) { 181 | if orig == nil { 182 | return nil, nil 183 | } 184 | ret := &SampleFJSON{} 185 | 186 | for _, info := range b._properties { 187 | if err := info.Encoder(orig, ret); err != nil { 188 | return nil, err 189 | } 190 | } 191 | 192 | return ret, nil 193 | } 194 | 195 | // ConvertList specified non-JSON slice to JSONList. 196 | func (b *SampleFJSONBuilder) ConvertList(orig []*SampleF) (SampleFJSONList, error) { 197 | if orig == nil { 198 | return nil, nil 199 | } 200 | 201 | list := make(SampleFJSONList, len(orig)) 202 | for idx, or := range orig { 203 | json, err := b.Convert(or) 204 | if err != nil { 205 | return nil, err 206 | } 207 | list[idx] = json 208 | } 209 | 210 | return list, nil 211 | } 212 | 213 | // Convert specified JSON object to non-JSON object. 214 | func (orig *SampleFJSON) Convert() (*SampleF, error) { 215 | ret := &SampleF{} 216 | 217 | b := NewSampleFJSONBuilder().AddAll() 218 | for _, info := range b._properties { 219 | if err := info.Decoder(orig, ret); err != nil { 220 | return nil, err 221 | } 222 | } 223 | 224 | return ret, nil 225 | } 226 | 227 | // Convert specified JSONList to non-JSON slice. 228 | func (jsonList SampleFJSONList) Convert() ([]*SampleF, error) { 229 | orig := ([]*SampleFJSON)(jsonList) 230 | 231 | list := make([]*SampleF, len(orig)) 232 | for idx, or := range orig { 233 | obj, err := or.Convert() 234 | if err != nil { 235 | return nil, err 236 | } 237 | list[idx] = obj 238 | } 239 | 240 | return list, nil 241 | } 242 | 243 | // Marshal non-JSON object to JSON string. 244 | func (b *SampleFJSONBuilder) Marshal(orig *SampleF) ([]byte, error) { 245 | ret, err := b.Convert(orig) 246 | if err != nil { 247 | return nil, err 248 | } 249 | return json.Marshal(ret) 250 | } 251 | -------------------------------------------------------------------------------- /misc/fixture/g/model.go: -------------------------------------------------------------------------------- 1 | package g 2 | 3 | // test for import statement support 4 | 5 | type Inner struct { 6 | A string 7 | } 8 | 9 | type Sample struct { 10 | A1 Inner 11 | A2 *Inner 12 | As1 []Inner 13 | As2 []*Inner 14 | As3 *[]Inner 15 | As4 *[]*Inner 16 | } 17 | -------------------------------------------------------------------------------- /misc/fixture/g/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample,Inner -output misc/fixture/g/model_json.go misc/fixture/g; DO NOT EDIT 2 | 3 | package g 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // InnerJSON is jsonized struct for Inner. 10 | type InnerJSON struct { 11 | A string `json:"a,omitempty"` 12 | } 13 | 14 | // InnerJSONList is synonym about []*InnerJSON. 15 | type InnerJSONList []*InnerJSON 16 | 17 | // InnerPropertyEncoder is property encoder for [1]sJSON. 18 | type InnerPropertyEncoder func(src *Inner, dest *InnerJSON) error 19 | 20 | // InnerPropertyDecoder is property decoder for [1]sJSON. 21 | type InnerPropertyDecoder func(src *InnerJSON, dest *Inner) error 22 | 23 | // InnerPropertyInfo stores property information. 24 | type InnerPropertyInfo struct { 25 | fieldName string 26 | jsonName string 27 | Encoder InnerPropertyEncoder 28 | Decoder InnerPropertyDecoder 29 | } 30 | 31 | // FieldName returns struct field name of property. 32 | func (info *InnerPropertyInfo) FieldName() string { 33 | return info.fieldName 34 | } 35 | 36 | // JSONName returns json field name of property. 37 | func (info *InnerPropertyInfo) JSONName() string { 38 | return info.jsonName 39 | } 40 | 41 | // InnerJSONBuilder convert between Inner to InnerJSON mutually. 42 | type InnerJSONBuilder struct { 43 | _properties map[string]*InnerPropertyInfo 44 | _jsonPropertyMap map[string]*InnerPropertyInfo 45 | _structPropertyMap map[string]*InnerPropertyInfo 46 | A *InnerPropertyInfo 47 | } 48 | 49 | // NewInnerJSONBuilder make new InnerJSONBuilder. 50 | func NewInnerJSONBuilder() *InnerJSONBuilder { 51 | jb := &InnerJSONBuilder{ 52 | _properties: map[string]*InnerPropertyInfo{}, 53 | _jsonPropertyMap: map[string]*InnerPropertyInfo{}, 54 | _structPropertyMap: map[string]*InnerPropertyInfo{}, 55 | A: &InnerPropertyInfo{ 56 | fieldName: "A", 57 | jsonName: "a", 58 | Encoder: func(src *Inner, dest *InnerJSON) error { 59 | if src == nil { 60 | return nil 61 | } 62 | dest.A = src.A 63 | return nil 64 | }, 65 | Decoder: func(src *InnerJSON, dest *Inner) error { 66 | if src == nil { 67 | return nil 68 | } 69 | dest.A = src.A 70 | return nil 71 | }, 72 | }, 73 | } 74 | jb._structPropertyMap["A"] = jb.A 75 | jb._jsonPropertyMap["a"] = jb.A 76 | return jb 77 | } 78 | 79 | // Properties returns all properties on InnerJSONBuilder. 80 | func (b *InnerJSONBuilder) Properties() []*InnerPropertyInfo { 81 | return []*InnerPropertyInfo{ 82 | b.A, 83 | } 84 | } 85 | 86 | // AddAll adds all property to InnerJSONBuilder. 87 | func (b *InnerJSONBuilder) AddAll() *InnerJSONBuilder { 88 | b._properties["A"] = b.A 89 | return b 90 | } 91 | 92 | // Add specified property to InnerJSONBuilder. 93 | func (b *InnerJSONBuilder) Add(infos ...*InnerPropertyInfo) *InnerJSONBuilder { 94 | for _, info := range infos { 95 | b._properties[info.fieldName] = info 96 | } 97 | return b 98 | } 99 | 100 | // AddByJSONNames add properties to InnerJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 101 | func (b *InnerJSONBuilder) AddByJSONNames(names ...string) *InnerJSONBuilder { 102 | for _, name := range names { 103 | info := b._jsonPropertyMap[name] 104 | if info == nil { 105 | continue 106 | } 107 | b._properties[info.fieldName] = info 108 | } 109 | return b 110 | } 111 | 112 | // AddByNames add properties to InnerJSONBuilder by struct property name. if name is not in the builder, it will ignore. 113 | func (b *InnerJSONBuilder) AddByNames(names ...string) *InnerJSONBuilder { 114 | for _, name := range names { 115 | info := b._structPropertyMap[name] 116 | if info == nil { 117 | continue 118 | } 119 | b._properties[info.fieldName] = info 120 | } 121 | return b 122 | } 123 | 124 | // Remove specified property to InnerJSONBuilder. 125 | func (b *InnerJSONBuilder) Remove(infos ...*InnerPropertyInfo) *InnerJSONBuilder { 126 | for _, info := range infos { 127 | delete(b._properties, info.fieldName) 128 | } 129 | return b 130 | } 131 | 132 | // RemoveByJSONNames remove properties to InnerJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 133 | func (b *InnerJSONBuilder) RemoveByJSONNames(names ...string) *InnerJSONBuilder { 134 | 135 | for _, name := range names { 136 | info := b._jsonPropertyMap[name] 137 | if info == nil { 138 | continue 139 | } 140 | delete(b._properties, info.fieldName) 141 | } 142 | return b 143 | } 144 | 145 | // RemoveByNames remove properties to InnerJSONBuilder by struct property name. if name is not in the builder, it will ignore. 146 | func (b *InnerJSONBuilder) RemoveByNames(names ...string) *InnerJSONBuilder { 147 | for _, name := range names { 148 | info := b._structPropertyMap[name] 149 | if info == nil { 150 | continue 151 | } 152 | delete(b._properties, info.fieldName) 153 | } 154 | return b 155 | } 156 | 157 | // Convert specified non-JSON object to JSON object. 158 | func (b *InnerJSONBuilder) Convert(orig *Inner) (*InnerJSON, error) { 159 | if orig == nil { 160 | return nil, nil 161 | } 162 | ret := &InnerJSON{} 163 | 164 | for _, info := range b._properties { 165 | if err := info.Encoder(orig, ret); err != nil { 166 | return nil, err 167 | } 168 | } 169 | 170 | return ret, nil 171 | } 172 | 173 | // ConvertList specified non-JSON slice to JSONList. 174 | func (b *InnerJSONBuilder) ConvertList(orig []*Inner) (InnerJSONList, error) { 175 | if orig == nil { 176 | return nil, nil 177 | } 178 | 179 | list := make(InnerJSONList, len(orig)) 180 | for idx, or := range orig { 181 | json, err := b.Convert(or) 182 | if err != nil { 183 | return nil, err 184 | } 185 | list[idx] = json 186 | } 187 | 188 | return list, nil 189 | } 190 | 191 | // Convert specified JSON object to non-JSON object. 192 | func (orig *InnerJSON) Convert() (*Inner, error) { 193 | ret := &Inner{} 194 | 195 | b := NewInnerJSONBuilder().AddAll() 196 | for _, info := range b._properties { 197 | if err := info.Decoder(orig, ret); err != nil { 198 | return nil, err 199 | } 200 | } 201 | 202 | return ret, nil 203 | } 204 | 205 | // Convert specified JSONList to non-JSON slice. 206 | func (jsonList InnerJSONList) Convert() ([]*Inner, error) { 207 | orig := ([]*InnerJSON)(jsonList) 208 | 209 | list := make([]*Inner, len(orig)) 210 | for idx, or := range orig { 211 | obj, err := or.Convert() 212 | if err != nil { 213 | return nil, err 214 | } 215 | list[idx] = obj 216 | } 217 | 218 | return list, nil 219 | } 220 | 221 | // Marshal non-JSON object to JSON string. 222 | func (b *InnerJSONBuilder) Marshal(orig *Inner) ([]byte, error) { 223 | ret, err := b.Convert(orig) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return json.Marshal(ret) 228 | } 229 | 230 | // SampleJSON is jsonized struct for Sample. 231 | type SampleJSON struct { 232 | A1 InnerJSON `json:"a1,omitempty"` 233 | A2 *InnerJSON `json:"a2,omitempty"` 234 | As1 []InnerJSON `json:"as1,omitempty"` 235 | As2 []*InnerJSON `json:"as2,omitempty"` 236 | As3 *[]InnerJSON `json:"as3,omitempty"` 237 | As4 *[]*InnerJSON `json:"as4,omitempty"` 238 | } 239 | 240 | // SampleJSONList is synonym about []*SampleJSON. 241 | type SampleJSONList []*SampleJSON 242 | 243 | // SamplePropertyEncoder is property encoder for [1]sJSON. 244 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 245 | 246 | // SamplePropertyDecoder is property decoder for [1]sJSON. 247 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 248 | 249 | // SamplePropertyInfo stores property information. 250 | type SamplePropertyInfo struct { 251 | fieldName string 252 | jsonName string 253 | Encoder SamplePropertyEncoder 254 | Decoder SamplePropertyDecoder 255 | } 256 | 257 | // FieldName returns struct field name of property. 258 | func (info *SamplePropertyInfo) FieldName() string { 259 | return info.fieldName 260 | } 261 | 262 | // JSONName returns json field name of property. 263 | func (info *SamplePropertyInfo) JSONName() string { 264 | return info.jsonName 265 | } 266 | 267 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 268 | type SampleJSONBuilder struct { 269 | _properties map[string]*SamplePropertyInfo 270 | _jsonPropertyMap map[string]*SamplePropertyInfo 271 | _structPropertyMap map[string]*SamplePropertyInfo 272 | A1 *SamplePropertyInfo 273 | A2 *SamplePropertyInfo 274 | As1 *SamplePropertyInfo 275 | As2 *SamplePropertyInfo 276 | As3 *SamplePropertyInfo 277 | As4 *SamplePropertyInfo 278 | } 279 | 280 | // NewSampleJSONBuilder make new SampleJSONBuilder. 281 | func NewSampleJSONBuilder() *SampleJSONBuilder { 282 | jb := &SampleJSONBuilder{ 283 | _properties: map[string]*SamplePropertyInfo{}, 284 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 285 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 286 | A1: &SamplePropertyInfo{ 287 | fieldName: "A1", 288 | jsonName: "a1", 289 | Encoder: func(src *Sample, dest *SampleJSON) error { 290 | if src == nil { 291 | return nil 292 | } 293 | d, err := NewInnerJSONBuilder().AddAll().Convert(&src.A1) 294 | if err != nil { 295 | return err 296 | } 297 | dest.A1 = *d 298 | return nil 299 | }, 300 | Decoder: func(src *SampleJSON, dest *Sample) error { 301 | if src == nil { 302 | return nil 303 | } 304 | d, err := src.A1.Convert() 305 | if err != nil { 306 | return err 307 | } 308 | dest.A1 = *d 309 | return nil 310 | }, 311 | }, 312 | A2: &SamplePropertyInfo{ 313 | fieldName: "A2", 314 | jsonName: "a2", 315 | Encoder: func(src *Sample, dest *SampleJSON) error { 316 | if src == nil { 317 | return nil 318 | } else if src.A2 == nil { 319 | return nil 320 | } 321 | d, err := NewInnerJSONBuilder().AddAll().Convert(src.A2) 322 | if err != nil { 323 | return err 324 | } 325 | dest.A2 = d 326 | return nil 327 | }, 328 | Decoder: func(src *SampleJSON, dest *Sample) error { 329 | if src == nil { 330 | return nil 331 | } else if src.A2 == nil { 332 | return nil 333 | } 334 | d, err := src.A2.Convert() 335 | if err != nil { 336 | return err 337 | } 338 | dest.A2 = d 339 | return nil 340 | }, 341 | }, 342 | As1: &SamplePropertyInfo{ 343 | fieldName: "As1", 344 | jsonName: "as1", 345 | Encoder: func(src *Sample, dest *SampleJSON) error { 346 | if src == nil { 347 | return nil 348 | } 349 | b := NewInnerJSONBuilder().AddAll() 350 | list := make([]InnerJSON, len(src.As1)) 351 | for idx, obj := range src.As1 { 352 | d, err := b.Convert(&obj) 353 | if err != nil { 354 | return err 355 | } 356 | list[idx] = *d 357 | } 358 | dest.As1 = list 359 | return nil 360 | }, 361 | Decoder: func(src *SampleJSON, dest *Sample) error { 362 | if src == nil { 363 | return nil 364 | } 365 | list := make([]Inner, len(src.As1)) 366 | for idx, obj := range src.As1 { 367 | d, err := obj.Convert() 368 | if err != nil { 369 | return err 370 | } 371 | list[idx] = *d 372 | } 373 | dest.As1 = list 374 | return nil 375 | }, 376 | }, 377 | As2: &SamplePropertyInfo{ 378 | fieldName: "As2", 379 | jsonName: "as2", 380 | Encoder: func(src *Sample, dest *SampleJSON) error { 381 | if src == nil { 382 | return nil 383 | } 384 | list, err := NewInnerJSONBuilder().AddAll().ConvertList(src.As2) 385 | if err != nil { 386 | return err 387 | } 388 | dest.As2 = ([]*InnerJSON)(list) 389 | return nil 390 | }, 391 | Decoder: func(src *SampleJSON, dest *Sample) error { 392 | if src == nil { 393 | return nil 394 | } 395 | list := make([]*Inner, len(src.As2)) 396 | for idx, obj := range src.As2 { 397 | if obj == nil { 398 | continue 399 | } 400 | d, err := obj.Convert() 401 | if err != nil { 402 | return err 403 | } 404 | list[idx] = d 405 | } 406 | dest.As2 = list 407 | return nil 408 | }, 409 | }, 410 | As3: &SamplePropertyInfo{ 411 | fieldName: "As3", 412 | jsonName: "as3", 413 | Encoder: func(src *Sample, dest *SampleJSON) error { 414 | if src == nil { 415 | return nil 416 | } else if src.As3 == nil { 417 | return nil 418 | } 419 | b := NewInnerJSONBuilder().AddAll() 420 | list := make([]InnerJSON, len(*src.As3)) 421 | for idx, obj := range *src.As3 { 422 | d, err := b.Convert(&obj) 423 | if err != nil { 424 | return err 425 | } 426 | list[idx] = *d 427 | } 428 | dest.As3 = &list 429 | return nil 430 | }, 431 | Decoder: func(src *SampleJSON, dest *Sample) error { 432 | if src == nil { 433 | return nil 434 | } else if src.As3 == nil { 435 | return nil 436 | } 437 | list := make([]Inner, len(*src.As3)) 438 | for idx, obj := range *src.As3 { 439 | d, err := obj.Convert() 440 | if err != nil { 441 | return err 442 | } 443 | list[idx] = *d 444 | } 445 | dest.As3 = &list 446 | return nil 447 | }, 448 | }, 449 | As4: &SamplePropertyInfo{ 450 | fieldName: "As4", 451 | jsonName: "as4", 452 | Encoder: func(src *Sample, dest *SampleJSON) error { 453 | if src == nil { 454 | return nil 455 | } else if src.As4 == nil { 456 | return nil 457 | } 458 | list, err := NewInnerJSONBuilder().AddAll().ConvertList(*src.As4) 459 | if err != nil { 460 | return err 461 | } 462 | dest.As4 = (*[]*InnerJSON)(&list) 463 | return nil 464 | }, 465 | Decoder: func(src *SampleJSON, dest *Sample) error { 466 | if src == nil { 467 | return nil 468 | } else if src.As4 == nil { 469 | return nil 470 | } 471 | list := make([]*Inner, len(*src.As4)) 472 | for idx, obj := range *src.As4 { 473 | if obj == nil { 474 | continue 475 | } 476 | d, err := obj.Convert() 477 | if err != nil { 478 | return err 479 | } 480 | list[idx] = d 481 | } 482 | dest.As4 = &list 483 | return nil 484 | }, 485 | }, 486 | } 487 | jb._structPropertyMap["A1"] = jb.A1 488 | jb._jsonPropertyMap["a1"] = jb.A1 489 | jb._structPropertyMap["A2"] = jb.A2 490 | jb._jsonPropertyMap["a2"] = jb.A2 491 | jb._structPropertyMap["As1"] = jb.As1 492 | jb._jsonPropertyMap["as1"] = jb.As1 493 | jb._structPropertyMap["As2"] = jb.As2 494 | jb._jsonPropertyMap["as2"] = jb.As2 495 | jb._structPropertyMap["As3"] = jb.As3 496 | jb._jsonPropertyMap["as3"] = jb.As3 497 | jb._structPropertyMap["As4"] = jb.As4 498 | jb._jsonPropertyMap["as4"] = jb.As4 499 | return jb 500 | } 501 | 502 | // Properties returns all properties on SampleJSONBuilder. 503 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 504 | return []*SamplePropertyInfo{ 505 | b.A1, 506 | b.A2, 507 | b.As1, 508 | b.As2, 509 | b.As3, 510 | b.As4, 511 | } 512 | } 513 | 514 | // AddAll adds all property to SampleJSONBuilder. 515 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 516 | b._properties["A1"] = b.A1 517 | b._properties["A2"] = b.A2 518 | b._properties["As1"] = b.As1 519 | b._properties["As2"] = b.As2 520 | b._properties["As3"] = b.As3 521 | b._properties["As4"] = b.As4 522 | return b 523 | } 524 | 525 | // Add specified property to SampleJSONBuilder. 526 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 527 | for _, info := range infos { 528 | b._properties[info.fieldName] = info 529 | } 530 | return b 531 | } 532 | 533 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 534 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 535 | for _, name := range names { 536 | info := b._jsonPropertyMap[name] 537 | if info == nil { 538 | continue 539 | } 540 | b._properties[info.fieldName] = info 541 | } 542 | return b 543 | } 544 | 545 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 546 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 547 | for _, name := range names { 548 | info := b._structPropertyMap[name] 549 | if info == nil { 550 | continue 551 | } 552 | b._properties[info.fieldName] = info 553 | } 554 | return b 555 | } 556 | 557 | // Remove specified property to SampleJSONBuilder. 558 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 559 | for _, info := range infos { 560 | delete(b._properties, info.fieldName) 561 | } 562 | return b 563 | } 564 | 565 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 566 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 567 | 568 | for _, name := range names { 569 | info := b._jsonPropertyMap[name] 570 | if info == nil { 571 | continue 572 | } 573 | delete(b._properties, info.fieldName) 574 | } 575 | return b 576 | } 577 | 578 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 579 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 580 | for _, name := range names { 581 | info := b._structPropertyMap[name] 582 | if info == nil { 583 | continue 584 | } 585 | delete(b._properties, info.fieldName) 586 | } 587 | return b 588 | } 589 | 590 | // Convert specified non-JSON object to JSON object. 591 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 592 | if orig == nil { 593 | return nil, nil 594 | } 595 | ret := &SampleJSON{} 596 | 597 | for _, info := range b._properties { 598 | if err := info.Encoder(orig, ret); err != nil { 599 | return nil, err 600 | } 601 | } 602 | 603 | return ret, nil 604 | } 605 | 606 | // ConvertList specified non-JSON slice to JSONList. 607 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 608 | if orig == nil { 609 | return nil, nil 610 | } 611 | 612 | list := make(SampleJSONList, len(orig)) 613 | for idx, or := range orig { 614 | json, err := b.Convert(or) 615 | if err != nil { 616 | return nil, err 617 | } 618 | list[idx] = json 619 | } 620 | 621 | return list, nil 622 | } 623 | 624 | // Convert specified JSON object to non-JSON object. 625 | func (orig *SampleJSON) Convert() (*Sample, error) { 626 | ret := &Sample{} 627 | 628 | b := NewSampleJSONBuilder().AddAll() 629 | for _, info := range b._properties { 630 | if err := info.Decoder(orig, ret); err != nil { 631 | return nil, err 632 | } 633 | } 634 | 635 | return ret, nil 636 | } 637 | 638 | // Convert specified JSONList to non-JSON slice. 639 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 640 | orig := ([]*SampleJSON)(jsonList) 641 | 642 | list := make([]*Sample, len(orig)) 643 | for idx, or := range orig { 644 | obj, err := or.Convert() 645 | if err != nil { 646 | return nil, err 647 | } 648 | list[idx] = obj 649 | } 650 | 651 | return list, nil 652 | } 653 | 654 | // Marshal non-JSON object to JSON string. 655 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 656 | ret, err := b.Convert(orig) 657 | if err != nil { 658 | return nil, err 659 | } 660 | return json.Marshal(ret) 661 | } 662 | -------------------------------------------------------------------------------- /misc/fixture/h/model.go: -------------------------------------------------------------------------------- 1 | package h 2 | 3 | type Sample struct { 4 | ID string 5 | } 6 | -------------------------------------------------------------------------------- /misc/fixture/h/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/h/model_json.go misc/fixture/h; DO NOT EDIT 2 | 3 | package h 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | ID string `json:"id,omitempty"` 12 | } 13 | 14 | // SampleJSONList is synonym about []*SampleJSON. 15 | type SampleJSONList []*SampleJSON 16 | 17 | // SamplePropertyEncoder is property encoder for [1]sJSON. 18 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 19 | 20 | // SamplePropertyDecoder is property decoder for [1]sJSON. 21 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 22 | 23 | // SamplePropertyInfo stores property information. 24 | type SamplePropertyInfo struct { 25 | fieldName string 26 | jsonName string 27 | Encoder SamplePropertyEncoder 28 | Decoder SamplePropertyDecoder 29 | } 30 | 31 | // FieldName returns struct field name of property. 32 | func (info *SamplePropertyInfo) FieldName() string { 33 | return info.fieldName 34 | } 35 | 36 | // JSONName returns json field name of property. 37 | func (info *SamplePropertyInfo) JSONName() string { 38 | return info.jsonName 39 | } 40 | 41 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 42 | type SampleJSONBuilder struct { 43 | _properties map[string]*SamplePropertyInfo 44 | _jsonPropertyMap map[string]*SamplePropertyInfo 45 | _structPropertyMap map[string]*SamplePropertyInfo 46 | ID *SamplePropertyInfo 47 | } 48 | 49 | // NewSampleJSONBuilder make new SampleJSONBuilder. 50 | func NewSampleJSONBuilder() *SampleJSONBuilder { 51 | jb := &SampleJSONBuilder{ 52 | _properties: map[string]*SamplePropertyInfo{}, 53 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 54 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 55 | ID: &SamplePropertyInfo{ 56 | fieldName: "ID", 57 | jsonName: "id", 58 | Encoder: func(src *Sample, dest *SampleJSON) error { 59 | if src == nil { 60 | return nil 61 | } 62 | dest.ID = src.ID 63 | return nil 64 | }, 65 | Decoder: func(src *SampleJSON, dest *Sample) error { 66 | if src == nil { 67 | return nil 68 | } 69 | dest.ID = src.ID 70 | return nil 71 | }, 72 | }, 73 | } 74 | jb._structPropertyMap["ID"] = jb.ID 75 | jb._jsonPropertyMap["id"] = jb.ID 76 | return jb 77 | } 78 | 79 | // Properties returns all properties on SampleJSONBuilder. 80 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 81 | return []*SamplePropertyInfo{ 82 | b.ID, 83 | } 84 | } 85 | 86 | // AddAll adds all property to SampleJSONBuilder. 87 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 88 | b._properties["ID"] = b.ID 89 | return b 90 | } 91 | 92 | // Add specified property to SampleJSONBuilder. 93 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 94 | for _, info := range infos { 95 | b._properties[info.fieldName] = info 96 | } 97 | return b 98 | } 99 | 100 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 101 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 102 | for _, name := range names { 103 | info := b._jsonPropertyMap[name] 104 | if info == nil { 105 | continue 106 | } 107 | b._properties[info.fieldName] = info 108 | } 109 | return b 110 | } 111 | 112 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 113 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 114 | for _, name := range names { 115 | info := b._structPropertyMap[name] 116 | if info == nil { 117 | continue 118 | } 119 | b._properties[info.fieldName] = info 120 | } 121 | return b 122 | } 123 | 124 | // Remove specified property to SampleJSONBuilder. 125 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 126 | for _, info := range infos { 127 | delete(b._properties, info.fieldName) 128 | } 129 | return b 130 | } 131 | 132 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 133 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 134 | 135 | for _, name := range names { 136 | info := b._jsonPropertyMap[name] 137 | if info == nil { 138 | continue 139 | } 140 | delete(b._properties, info.fieldName) 141 | } 142 | return b 143 | } 144 | 145 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 146 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 147 | for _, name := range names { 148 | info := b._structPropertyMap[name] 149 | if info == nil { 150 | continue 151 | } 152 | delete(b._properties, info.fieldName) 153 | } 154 | return b 155 | } 156 | 157 | // Convert specified non-JSON object to JSON object. 158 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 159 | if orig == nil { 160 | return nil, nil 161 | } 162 | ret := &SampleJSON{} 163 | 164 | for _, info := range b._properties { 165 | if err := info.Encoder(orig, ret); err != nil { 166 | return nil, err 167 | } 168 | } 169 | 170 | return ret, nil 171 | } 172 | 173 | // ConvertList specified non-JSON slice to JSONList. 174 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 175 | if orig == nil { 176 | return nil, nil 177 | } 178 | 179 | list := make(SampleJSONList, len(orig)) 180 | for idx, or := range orig { 181 | json, err := b.Convert(or) 182 | if err != nil { 183 | return nil, err 184 | } 185 | list[idx] = json 186 | } 187 | 188 | return list, nil 189 | } 190 | 191 | // Convert specified JSON object to non-JSON object. 192 | func (orig *SampleJSON) Convert() (*Sample, error) { 193 | ret := &Sample{} 194 | 195 | b := NewSampleJSONBuilder().AddAll() 196 | for _, info := range b._properties { 197 | if err := info.Decoder(orig, ret); err != nil { 198 | return nil, err 199 | } 200 | } 201 | 202 | return ret, nil 203 | } 204 | 205 | // Convert specified JSONList to non-JSON slice. 206 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 207 | orig := ([]*SampleJSON)(jsonList) 208 | 209 | list := make([]*Sample, len(orig)) 210 | for idx, or := range orig { 211 | obj, err := or.Convert() 212 | if err != nil { 213 | return nil, err 214 | } 215 | list[idx] = obj 216 | } 217 | 218 | return list, nil 219 | } 220 | 221 | // Marshal non-JSON object to JSON string. 222 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 223 | ret, err := b.Convert(orig) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return json.Marshal(ret) 228 | } 229 | -------------------------------------------------------------------------------- /misc/fixture/i/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -output model_json.go . 2 | 3 | package i 4 | 5 | // +jwg 6 | type Person struct { 7 | Name string 8 | Age int 9 | Password string 10 | } 11 | 12 | // +jwg 13 | type People struct { 14 | ShowPrivateInfo bool 15 | List []*Person 16 | } 17 | -------------------------------------------------------------------------------- /misc/fixture/i/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -output misc/fixture/i/model_json.go misc/fixture/i; DO NOT EDIT 2 | 3 | package i 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // PersonJSON is jsonized struct for Person. 10 | type PersonJSON struct { 11 | Name string `json:"name,omitempty"` 12 | Age int `json:"age,omitempty"` 13 | Password string `json:"password,omitempty"` 14 | } 15 | 16 | // PersonJSONList is synonym about []*PersonJSON. 17 | type PersonJSONList []*PersonJSON 18 | 19 | // PersonPropertyEncoder is property encoder for [1]sJSON. 20 | type PersonPropertyEncoder func(src *Person, dest *PersonJSON) error 21 | 22 | // PersonPropertyDecoder is property decoder for [1]sJSON. 23 | type PersonPropertyDecoder func(src *PersonJSON, dest *Person) error 24 | 25 | // PersonPropertyInfo stores property information. 26 | type PersonPropertyInfo struct { 27 | fieldName string 28 | jsonName string 29 | Encoder PersonPropertyEncoder 30 | Decoder PersonPropertyDecoder 31 | } 32 | 33 | // FieldName returns struct field name of property. 34 | func (info *PersonPropertyInfo) FieldName() string { 35 | return info.fieldName 36 | } 37 | 38 | // JSONName returns json field name of property. 39 | func (info *PersonPropertyInfo) JSONName() string { 40 | return info.jsonName 41 | } 42 | 43 | // PersonJSONBuilder convert between Person to PersonJSON mutually. 44 | type PersonJSONBuilder struct { 45 | _properties map[string]*PersonPropertyInfo 46 | _jsonPropertyMap map[string]*PersonPropertyInfo 47 | _structPropertyMap map[string]*PersonPropertyInfo 48 | Name *PersonPropertyInfo 49 | Age *PersonPropertyInfo 50 | Password *PersonPropertyInfo 51 | } 52 | 53 | // NewPersonJSONBuilder make new PersonJSONBuilder. 54 | func NewPersonJSONBuilder() *PersonJSONBuilder { 55 | jb := &PersonJSONBuilder{ 56 | _properties: map[string]*PersonPropertyInfo{}, 57 | _jsonPropertyMap: map[string]*PersonPropertyInfo{}, 58 | _structPropertyMap: map[string]*PersonPropertyInfo{}, 59 | Name: &PersonPropertyInfo{ 60 | fieldName: "Name", 61 | jsonName: "name", 62 | Encoder: func(src *Person, dest *PersonJSON) error { 63 | if src == nil { 64 | return nil 65 | } 66 | dest.Name = src.Name 67 | return nil 68 | }, 69 | Decoder: func(src *PersonJSON, dest *Person) error { 70 | if src == nil { 71 | return nil 72 | } 73 | dest.Name = src.Name 74 | return nil 75 | }, 76 | }, 77 | Age: &PersonPropertyInfo{ 78 | fieldName: "Age", 79 | jsonName: "age", 80 | Encoder: func(src *Person, dest *PersonJSON) error { 81 | if src == nil { 82 | return nil 83 | } 84 | dest.Age = src.Age 85 | return nil 86 | }, 87 | Decoder: func(src *PersonJSON, dest *Person) error { 88 | if src == nil { 89 | return nil 90 | } 91 | dest.Age = src.Age 92 | return nil 93 | }, 94 | }, 95 | Password: &PersonPropertyInfo{ 96 | fieldName: "Password", 97 | jsonName: "password", 98 | Encoder: func(src *Person, dest *PersonJSON) error { 99 | if src == nil { 100 | return nil 101 | } 102 | dest.Password = src.Password 103 | return nil 104 | }, 105 | Decoder: func(src *PersonJSON, dest *Person) error { 106 | if src == nil { 107 | return nil 108 | } 109 | dest.Password = src.Password 110 | return nil 111 | }, 112 | }, 113 | } 114 | jb._structPropertyMap["Name"] = jb.Name 115 | jb._jsonPropertyMap["name"] = jb.Name 116 | jb._structPropertyMap["Age"] = jb.Age 117 | jb._jsonPropertyMap["age"] = jb.Age 118 | jb._structPropertyMap["Password"] = jb.Password 119 | jb._jsonPropertyMap["password"] = jb.Password 120 | return jb 121 | } 122 | 123 | // Properties returns all properties on PersonJSONBuilder. 124 | func (b *PersonJSONBuilder) Properties() []*PersonPropertyInfo { 125 | return []*PersonPropertyInfo{ 126 | b.Name, 127 | b.Age, 128 | b.Password, 129 | } 130 | } 131 | 132 | // AddAll adds all property to PersonJSONBuilder. 133 | func (b *PersonJSONBuilder) AddAll() *PersonJSONBuilder { 134 | b._properties["Name"] = b.Name 135 | b._properties["Age"] = b.Age 136 | b._properties["Password"] = b.Password 137 | return b 138 | } 139 | 140 | // Add specified property to PersonJSONBuilder. 141 | func (b *PersonJSONBuilder) Add(info *PersonPropertyInfo) *PersonJSONBuilder { 142 | b._properties[info.fieldName] = info 143 | return b 144 | } 145 | 146 | // AddByJSONNames add properties to PersonJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 147 | func (b *PersonJSONBuilder) AddByJSONNames(names ...string) *PersonJSONBuilder { 148 | for _, name := range names { 149 | info := b._jsonPropertyMap[name] 150 | if info == nil { 151 | continue 152 | } 153 | b._properties[info.fieldName] = info 154 | } 155 | return b 156 | } 157 | 158 | // AddByNames add properties to PersonJSONBuilder by struct property name. if name is not in the builder, it will ignore. 159 | func (b *PersonJSONBuilder) AddByNames(names ...string) *PersonJSONBuilder { 160 | for _, name := range names { 161 | info := b._structPropertyMap[name] 162 | if info == nil { 163 | continue 164 | } 165 | b._properties[info.fieldName] = info 166 | } 167 | return b 168 | } 169 | 170 | // Remove specified property to PersonJSONBuilder. 171 | func (b *PersonJSONBuilder) Remove(info *PersonPropertyInfo) *PersonJSONBuilder { 172 | delete(b._properties, info.fieldName) 173 | return b 174 | } 175 | 176 | // RemoveByJSONNames remove properties to PersonJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 177 | func (b *PersonJSONBuilder) RemoveByJSONNames(names ...string) *PersonJSONBuilder { 178 | 179 | for _, name := range names { 180 | info := b._jsonPropertyMap[name] 181 | if info == nil { 182 | continue 183 | } 184 | delete(b._properties, info.fieldName) 185 | } 186 | return b 187 | } 188 | 189 | // RemoveByNames remove properties to PersonJSONBuilder by struct property name. if name is not in the builder, it will ignore. 190 | func (b *PersonJSONBuilder) RemoveByNames(names ...string) *PersonJSONBuilder { 191 | for _, name := range names { 192 | info := b._structPropertyMap[name] 193 | if info == nil { 194 | continue 195 | } 196 | delete(b._properties, info.fieldName) 197 | } 198 | return b 199 | } 200 | 201 | // Convert specified non-JSON object to JSON object. 202 | func (b *PersonJSONBuilder) Convert(orig *Person) (*PersonJSON, error) { 203 | if orig == nil { 204 | return nil, nil 205 | } 206 | ret := &PersonJSON{} 207 | 208 | for _, info := range b._properties { 209 | if err := info.Encoder(orig, ret); err != nil { 210 | return nil, err 211 | } 212 | } 213 | 214 | return ret, nil 215 | } 216 | 217 | // ConvertList specified non-JSON slice to JSONList. 218 | func (b *PersonJSONBuilder) ConvertList(orig []*Person) (PersonJSONList, error) { 219 | if orig == nil { 220 | return nil, nil 221 | } 222 | 223 | list := make(PersonJSONList, len(orig)) 224 | for idx, or := range orig { 225 | json, err := b.Convert(or) 226 | if err != nil { 227 | return nil, err 228 | } 229 | list[idx] = json 230 | } 231 | 232 | return list, nil 233 | } 234 | 235 | // Convert specified JSON object to non-JSON object. 236 | func (orig *PersonJSON) Convert() (*Person, error) { 237 | ret := &Person{} 238 | 239 | b := NewPersonJSONBuilder().AddAll() 240 | for _, info := range b._properties { 241 | if err := info.Decoder(orig, ret); err != nil { 242 | return nil, err 243 | } 244 | } 245 | 246 | return ret, nil 247 | } 248 | 249 | // Convert specified JSONList to non-JSON slice. 250 | func (jsonList PersonJSONList) Convert() ([]*Person, error) { 251 | orig := ([]*PersonJSON)(jsonList) 252 | 253 | list := make([]*Person, len(orig)) 254 | for idx, or := range orig { 255 | obj, err := or.Convert() 256 | if err != nil { 257 | return nil, err 258 | } 259 | list[idx] = obj 260 | } 261 | 262 | return list, nil 263 | } 264 | 265 | // Marshal non-JSON object to JSON string. 266 | func (b *PersonJSONBuilder) Marshal(orig *Person) ([]byte, error) { 267 | ret, err := b.Convert(orig) 268 | if err != nil { 269 | return nil, err 270 | } 271 | return json.Marshal(ret) 272 | } 273 | 274 | // PeopleJSON is jsonized struct for People. 275 | type PeopleJSON struct { 276 | ShowPrivateInfo bool `json:"showPrivateInfo,omitempty"` 277 | List []*PersonJSON `json:"list,omitempty"` 278 | } 279 | 280 | // PeopleJSONList is synonym about []*PeopleJSON. 281 | type PeopleJSONList []*PeopleJSON 282 | 283 | // PeoplePropertyEncoder is property encoder for [1]sJSON. 284 | type PeoplePropertyEncoder func(src *People, dest *PeopleJSON) error 285 | 286 | // PeoplePropertyDecoder is property decoder for [1]sJSON. 287 | type PeoplePropertyDecoder func(src *PeopleJSON, dest *People) error 288 | 289 | // PeoplePropertyInfo stores property information. 290 | type PeoplePropertyInfo struct { 291 | fieldName string 292 | jsonName string 293 | Encoder PeoplePropertyEncoder 294 | Decoder PeoplePropertyDecoder 295 | } 296 | 297 | // FieldName returns struct field name of property. 298 | func (info *PeoplePropertyInfo) FieldName() string { 299 | return info.fieldName 300 | } 301 | 302 | // JSONName returns json field name of property. 303 | func (info *PeoplePropertyInfo) JSONName() string { 304 | return info.jsonName 305 | } 306 | 307 | // PeopleJSONBuilder convert between People to PeopleJSON mutually. 308 | type PeopleJSONBuilder struct { 309 | _properties map[string]*PeoplePropertyInfo 310 | _jsonPropertyMap map[string]*PeoplePropertyInfo 311 | _structPropertyMap map[string]*PeoplePropertyInfo 312 | ShowPrivateInfo *PeoplePropertyInfo 313 | List *PeoplePropertyInfo 314 | } 315 | 316 | // NewPeopleJSONBuilder make new PeopleJSONBuilder. 317 | func NewPeopleJSONBuilder() *PeopleJSONBuilder { 318 | jb := &PeopleJSONBuilder{ 319 | _properties: map[string]*PeoplePropertyInfo{}, 320 | _jsonPropertyMap: map[string]*PeoplePropertyInfo{}, 321 | _structPropertyMap: map[string]*PeoplePropertyInfo{}, 322 | ShowPrivateInfo: &PeoplePropertyInfo{ 323 | fieldName: "ShowPrivateInfo", 324 | jsonName: "showPrivateInfo", 325 | Encoder: func(src *People, dest *PeopleJSON) error { 326 | if src == nil { 327 | return nil 328 | } 329 | dest.ShowPrivateInfo = src.ShowPrivateInfo 330 | return nil 331 | }, 332 | Decoder: func(src *PeopleJSON, dest *People) error { 333 | if src == nil { 334 | return nil 335 | } 336 | dest.ShowPrivateInfo = src.ShowPrivateInfo 337 | return nil 338 | }, 339 | }, 340 | List: &PeoplePropertyInfo{ 341 | fieldName: "List", 342 | jsonName: "list", 343 | Encoder: func(src *People, dest *PeopleJSON) error { 344 | if src == nil { 345 | return nil 346 | } 347 | list, err := NewPersonJSONBuilder().AddAll().ConvertList(src.List) 348 | if err != nil { 349 | return err 350 | } 351 | dest.List = ([]*PersonJSON)(list) 352 | return nil 353 | }, 354 | Decoder: func(src *PeopleJSON, dest *People) error { 355 | if src == nil { 356 | return nil 357 | } 358 | list := make([]*Person, len(src.List)) 359 | for idx, obj := range src.List { 360 | if obj == nil { 361 | continue 362 | } 363 | d, err := obj.Convert() 364 | if err != nil { 365 | return err 366 | } 367 | list[idx] = d 368 | } 369 | dest.List = list 370 | return nil 371 | }, 372 | }, 373 | } 374 | jb._structPropertyMap["ShowPrivateInfo"] = jb.ShowPrivateInfo 375 | jb._jsonPropertyMap["showPrivateInfo"] = jb.ShowPrivateInfo 376 | jb._structPropertyMap["List"] = jb.List 377 | jb._jsonPropertyMap["list"] = jb.List 378 | return jb 379 | } 380 | 381 | // Properties returns all properties on PeopleJSONBuilder. 382 | func (b *PeopleJSONBuilder) Properties() []*PeoplePropertyInfo { 383 | return []*PeoplePropertyInfo{ 384 | b.ShowPrivateInfo, 385 | b.List, 386 | } 387 | } 388 | 389 | // AddAll adds all property to PeopleJSONBuilder. 390 | func (b *PeopleJSONBuilder) AddAll() *PeopleJSONBuilder { 391 | b._properties["ShowPrivateInfo"] = b.ShowPrivateInfo 392 | b._properties["List"] = b.List 393 | return b 394 | } 395 | 396 | // Add specified property to PeopleJSONBuilder. 397 | func (b *PeopleJSONBuilder) Add(info *PeoplePropertyInfo) *PeopleJSONBuilder { 398 | b._properties[info.fieldName] = info 399 | return b 400 | } 401 | 402 | // AddByJSONNames add properties to PeopleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 403 | func (b *PeopleJSONBuilder) AddByJSONNames(names ...string) *PeopleJSONBuilder { 404 | for _, name := range names { 405 | info := b._jsonPropertyMap[name] 406 | if info == nil { 407 | continue 408 | } 409 | b._properties[info.fieldName] = info 410 | } 411 | return b 412 | } 413 | 414 | // AddByNames add properties to PeopleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 415 | func (b *PeopleJSONBuilder) AddByNames(names ...string) *PeopleJSONBuilder { 416 | for _, name := range names { 417 | info := b._structPropertyMap[name] 418 | if info == nil { 419 | continue 420 | } 421 | b._properties[info.fieldName] = info 422 | } 423 | return b 424 | } 425 | 426 | // Remove specified property to PeopleJSONBuilder. 427 | func (b *PeopleJSONBuilder) Remove(info *PeoplePropertyInfo) *PeopleJSONBuilder { 428 | delete(b._properties, info.fieldName) 429 | return b 430 | } 431 | 432 | // RemoveByJSONNames remove properties to PeopleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 433 | func (b *PeopleJSONBuilder) RemoveByJSONNames(names ...string) *PeopleJSONBuilder { 434 | 435 | for _, name := range names { 436 | info := b._jsonPropertyMap[name] 437 | if info == nil { 438 | continue 439 | } 440 | delete(b._properties, info.fieldName) 441 | } 442 | return b 443 | } 444 | 445 | // RemoveByNames remove properties to PeopleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 446 | func (b *PeopleJSONBuilder) RemoveByNames(names ...string) *PeopleJSONBuilder { 447 | for _, name := range names { 448 | info := b._structPropertyMap[name] 449 | if info == nil { 450 | continue 451 | } 452 | delete(b._properties, info.fieldName) 453 | } 454 | return b 455 | } 456 | 457 | // Convert specified non-JSON object to JSON object. 458 | func (b *PeopleJSONBuilder) Convert(orig *People) (*PeopleJSON, error) { 459 | if orig == nil { 460 | return nil, nil 461 | } 462 | ret := &PeopleJSON{} 463 | 464 | for _, info := range b._properties { 465 | if err := info.Encoder(orig, ret); err != nil { 466 | return nil, err 467 | } 468 | } 469 | 470 | return ret, nil 471 | } 472 | 473 | // ConvertList specified non-JSON slice to JSONList. 474 | func (b *PeopleJSONBuilder) ConvertList(orig []*People) (PeopleJSONList, error) { 475 | if orig == nil { 476 | return nil, nil 477 | } 478 | 479 | list := make(PeopleJSONList, len(orig)) 480 | for idx, or := range orig { 481 | json, err := b.Convert(or) 482 | if err != nil { 483 | return nil, err 484 | } 485 | list[idx] = json 486 | } 487 | 488 | return list, nil 489 | } 490 | 491 | // Convert specified JSON object to non-JSON object. 492 | func (orig *PeopleJSON) Convert() (*People, error) { 493 | ret := &People{} 494 | 495 | b := NewPeopleJSONBuilder().AddAll() 496 | for _, info := range b._properties { 497 | if err := info.Decoder(orig, ret); err != nil { 498 | return nil, err 499 | } 500 | } 501 | 502 | return ret, nil 503 | } 504 | 505 | // Convert specified JSONList to non-JSON slice. 506 | func (jsonList PeopleJSONList) Convert() ([]*People, error) { 507 | orig := ([]*PeopleJSON)(jsonList) 508 | 509 | list := make([]*People, len(orig)) 510 | for idx, or := range orig { 511 | obj, err := or.Convert() 512 | if err != nil { 513 | return nil, err 514 | } 515 | list[idx] = obj 516 | } 517 | 518 | return list, nil 519 | } 520 | 521 | // Marshal non-JSON object to JSON string. 522 | func (b *PeopleJSONBuilder) Marshal(orig *People) ([]byte, error) { 523 | ret, err := b.Convert(orig) 524 | if err != nil { 525 | return nil, err 526 | } 527 | return json.Marshal(ret) 528 | } 529 | -------------------------------------------------------------------------------- /misc/fixture/j/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -output model_json.go . 2 | 3 | package j 4 | 5 | // +jwg 6 | type Foo struct { 7 | Tmp *Temp 8 | Bar 9 | *Buzz 10 | Hoge 11 | *Fuga 12 | } 13 | 14 | type Temp struct { 15 | Temp1 string 16 | } 17 | 18 | type Bar struct { 19 | Bar1 string 20 | } 21 | 22 | type Buzz struct { 23 | Buzz1 string 24 | } 25 | 26 | // +jwg 27 | type Hoge struct { 28 | Hoge1 string 29 | } 30 | 31 | // +jwg 32 | type Fuga struct { 33 | Fuga1 string 34 | } 35 | -------------------------------------------------------------------------------- /misc/fixture/j/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -output misc/fixture/j/model_json.go misc/fixture/j; DO NOT EDIT 2 | 3 | package j 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // FooJSON is jsonized struct for Foo. 10 | type FooJSON struct { 11 | Tmp *Temp `json:"tmp,omitempty"` 12 | Bar `json:",omitempty"` 13 | *Buzz `json:",omitempty"` 14 | HogeJSON `json:",omitempty"` 15 | *FugaJSON `json:",omitempty"` 16 | } 17 | 18 | // FooJSONList is synonym about []*FooJSON. 19 | type FooJSONList []*FooJSON 20 | 21 | // FooPropertyEncoder is property encoder for [1]sJSON. 22 | type FooPropertyEncoder func(src *Foo, dest *FooJSON) error 23 | 24 | // FooPropertyDecoder is property decoder for [1]sJSON. 25 | type FooPropertyDecoder func(src *FooJSON, dest *Foo) error 26 | 27 | // FooPropertyInfo stores property information. 28 | type FooPropertyInfo struct { 29 | fieldName string 30 | jsonName string 31 | Encoder FooPropertyEncoder 32 | Decoder FooPropertyDecoder 33 | } 34 | 35 | // FieldName returns struct field name of property. 36 | func (info *FooPropertyInfo) FieldName() string { 37 | return info.fieldName 38 | } 39 | 40 | // JSONName returns json field name of property. 41 | func (info *FooPropertyInfo) JSONName() string { 42 | return info.jsonName 43 | } 44 | 45 | // FooJSONBuilder convert between Foo to FooJSON mutually. 46 | type FooJSONBuilder struct { 47 | _properties map[string]*FooPropertyInfo 48 | _jsonPropertyMap map[string]*FooPropertyInfo 49 | _structPropertyMap map[string]*FooPropertyInfo 50 | Tmp *FooPropertyInfo 51 | Bar *FooPropertyInfo 52 | Buzz *FooPropertyInfo 53 | Hoge *FooPropertyInfo 54 | Fuga *FooPropertyInfo 55 | } 56 | 57 | // NewFooJSONBuilder make new FooJSONBuilder. 58 | func NewFooJSONBuilder() *FooJSONBuilder { 59 | jb := &FooJSONBuilder{ 60 | _properties: map[string]*FooPropertyInfo{}, 61 | _jsonPropertyMap: map[string]*FooPropertyInfo{}, 62 | _structPropertyMap: map[string]*FooPropertyInfo{}, 63 | Tmp: &FooPropertyInfo{ 64 | fieldName: "Tmp", 65 | jsonName: "tmp", 66 | Encoder: func(src *Foo, dest *FooJSON) error { 67 | if src == nil { 68 | return nil 69 | } 70 | dest.Tmp = src.Tmp 71 | return nil 72 | }, 73 | Decoder: func(src *FooJSON, dest *Foo) error { 74 | if src == nil { 75 | return nil 76 | } 77 | dest.Tmp = src.Tmp 78 | return nil 79 | }, 80 | }, 81 | Bar: &FooPropertyInfo{ 82 | fieldName: "Bar", 83 | jsonName: "", 84 | Encoder: func(src *Foo, dest *FooJSON) error { 85 | if src == nil { 86 | return nil 87 | } 88 | dest.Bar = src.Bar 89 | return nil 90 | }, 91 | Decoder: func(src *FooJSON, dest *Foo) error { 92 | if src == nil { 93 | return nil 94 | } 95 | dest.Bar = src.Bar 96 | return nil 97 | }, 98 | }, 99 | Buzz: &FooPropertyInfo{ 100 | fieldName: "Buzz", 101 | jsonName: "", 102 | Encoder: func(src *Foo, dest *FooJSON) error { 103 | if src == nil { 104 | return nil 105 | } 106 | dest.Buzz = src.Buzz 107 | return nil 108 | }, 109 | Decoder: func(src *FooJSON, dest *Foo) error { 110 | if src == nil { 111 | return nil 112 | } 113 | dest.Buzz = src.Buzz 114 | return nil 115 | }, 116 | }, 117 | Hoge: &FooPropertyInfo{ 118 | fieldName: "Hoge", 119 | jsonName: "", 120 | Encoder: func(src *Foo, dest *FooJSON) error { 121 | if src == nil { 122 | return nil 123 | } 124 | d, err := NewHogeJSONBuilder().AddAll().Convert(&src.Hoge) 125 | if err != nil { 126 | return err 127 | } 128 | dest.HogeJSON = *d 129 | return nil 130 | }, 131 | Decoder: func(src *FooJSON, dest *Foo) error { 132 | if src == nil { 133 | return nil 134 | } 135 | d, err := src.HogeJSON.Convert() 136 | if err != nil { 137 | return err 138 | } 139 | dest.Hoge = *d 140 | return nil 141 | }, 142 | }, 143 | Fuga: &FooPropertyInfo{ 144 | fieldName: "Fuga", 145 | jsonName: "", 146 | Encoder: func(src *Foo, dest *FooJSON) error { 147 | if src == nil { 148 | return nil 149 | } else if src.Fuga == nil { 150 | return nil 151 | } 152 | d, err := NewFugaJSONBuilder().AddAll().Convert(src.Fuga) 153 | if err != nil { 154 | return err 155 | } 156 | dest.FugaJSON = d 157 | return nil 158 | }, 159 | Decoder: func(src *FooJSON, dest *Foo) error { 160 | if src == nil { 161 | return nil 162 | } else if src.FugaJSON == nil { 163 | return nil 164 | } 165 | d, err := src.FugaJSON.Convert() 166 | if err != nil { 167 | return err 168 | } 169 | dest.Fuga = d 170 | return nil 171 | }, 172 | }, 173 | } 174 | jb._structPropertyMap["Tmp"] = jb.Tmp 175 | jb._jsonPropertyMap["tmp"] = jb.Tmp 176 | jb._structPropertyMap["Bar"] = jb.Bar 177 | jb._jsonPropertyMap[""] = jb.Bar 178 | jb._structPropertyMap["Buzz"] = jb.Buzz 179 | jb._jsonPropertyMap[""] = jb.Buzz 180 | jb._structPropertyMap["Hoge"] = jb.Hoge 181 | jb._jsonPropertyMap[""] = jb.Hoge 182 | jb._structPropertyMap["Fuga"] = jb.Fuga 183 | jb._jsonPropertyMap[""] = jb.Fuga 184 | return jb 185 | } 186 | 187 | // Properties returns all properties on FooJSONBuilder. 188 | func (b *FooJSONBuilder) Properties() []*FooPropertyInfo { 189 | return []*FooPropertyInfo{ 190 | b.Tmp, 191 | b.Bar, 192 | b.Buzz, 193 | b.Hoge, 194 | b.Fuga, 195 | } 196 | } 197 | 198 | // AddAll adds all property to FooJSONBuilder. 199 | func (b *FooJSONBuilder) AddAll() *FooJSONBuilder { 200 | b._properties["Tmp"] = b.Tmp 201 | b._properties["Bar"] = b.Bar 202 | b._properties["Buzz"] = b.Buzz 203 | b._properties["Hoge"] = b.Hoge 204 | b._properties["Fuga"] = b.Fuga 205 | return b 206 | } 207 | 208 | // Add specified property to FooJSONBuilder. 209 | func (b *FooJSONBuilder) Add(info *FooPropertyInfo) *FooJSONBuilder { 210 | b._properties[info.fieldName] = info 211 | return b 212 | } 213 | 214 | // AddByJSONNames add properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 215 | func (b *FooJSONBuilder) AddByJSONNames(names ...string) *FooJSONBuilder { 216 | for _, name := range names { 217 | info := b._jsonPropertyMap[name] 218 | if info == nil { 219 | continue 220 | } 221 | b._properties[info.fieldName] = info 222 | } 223 | return b 224 | } 225 | 226 | // AddByNames add properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore. 227 | func (b *FooJSONBuilder) AddByNames(names ...string) *FooJSONBuilder { 228 | for _, name := range names { 229 | info := b._structPropertyMap[name] 230 | if info == nil { 231 | continue 232 | } 233 | b._properties[info.fieldName] = info 234 | } 235 | return b 236 | } 237 | 238 | // Remove specified property to FooJSONBuilder. 239 | func (b *FooJSONBuilder) Remove(info *FooPropertyInfo) *FooJSONBuilder { 240 | delete(b._properties, info.fieldName) 241 | return b 242 | } 243 | 244 | // RemoveByJSONNames remove properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 245 | func (b *FooJSONBuilder) RemoveByJSONNames(names ...string) *FooJSONBuilder { 246 | 247 | for _, name := range names { 248 | info := b._jsonPropertyMap[name] 249 | if info == nil { 250 | continue 251 | } 252 | delete(b._properties, info.fieldName) 253 | } 254 | return b 255 | } 256 | 257 | // RemoveByNames remove properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore. 258 | func (b *FooJSONBuilder) RemoveByNames(names ...string) *FooJSONBuilder { 259 | for _, name := range names { 260 | info := b._structPropertyMap[name] 261 | if info == nil { 262 | continue 263 | } 264 | delete(b._properties, info.fieldName) 265 | } 266 | return b 267 | } 268 | 269 | // Convert specified non-JSON object to JSON object. 270 | func (b *FooJSONBuilder) Convert(orig *Foo) (*FooJSON, error) { 271 | if orig == nil { 272 | return nil, nil 273 | } 274 | ret := &FooJSON{} 275 | 276 | for _, info := range b._properties { 277 | if err := info.Encoder(orig, ret); err != nil { 278 | return nil, err 279 | } 280 | } 281 | 282 | return ret, nil 283 | } 284 | 285 | // ConvertList specified non-JSON slice to JSONList. 286 | func (b *FooJSONBuilder) ConvertList(orig []*Foo) (FooJSONList, error) { 287 | if orig == nil { 288 | return nil, nil 289 | } 290 | 291 | list := make(FooJSONList, len(orig)) 292 | for idx, or := range orig { 293 | json, err := b.Convert(or) 294 | if err != nil { 295 | return nil, err 296 | } 297 | list[idx] = json 298 | } 299 | 300 | return list, nil 301 | } 302 | 303 | // Convert specified JSON object to non-JSON object. 304 | func (orig *FooJSON) Convert() (*Foo, error) { 305 | ret := &Foo{} 306 | 307 | b := NewFooJSONBuilder().AddAll() 308 | for _, info := range b._properties { 309 | if err := info.Decoder(orig, ret); err != nil { 310 | return nil, err 311 | } 312 | } 313 | 314 | return ret, nil 315 | } 316 | 317 | // Convert specified JSONList to non-JSON slice. 318 | func (jsonList FooJSONList) Convert() ([]*Foo, error) { 319 | orig := ([]*FooJSON)(jsonList) 320 | 321 | list := make([]*Foo, len(orig)) 322 | for idx, or := range orig { 323 | obj, err := or.Convert() 324 | if err != nil { 325 | return nil, err 326 | } 327 | list[idx] = obj 328 | } 329 | 330 | return list, nil 331 | } 332 | 333 | // Marshal non-JSON object to JSON string. 334 | func (b *FooJSONBuilder) Marshal(orig *Foo) ([]byte, error) { 335 | ret, err := b.Convert(orig) 336 | if err != nil { 337 | return nil, err 338 | } 339 | return json.Marshal(ret) 340 | } 341 | 342 | // HogeJSON is jsonized struct for Hoge. 343 | type HogeJSON struct { 344 | Hoge1 string `json:"hoge1,omitempty"` 345 | } 346 | 347 | // HogeJSONList is synonym about []*HogeJSON. 348 | type HogeJSONList []*HogeJSON 349 | 350 | // HogePropertyEncoder is property encoder for [1]sJSON. 351 | type HogePropertyEncoder func(src *Hoge, dest *HogeJSON) error 352 | 353 | // HogePropertyDecoder is property decoder for [1]sJSON. 354 | type HogePropertyDecoder func(src *HogeJSON, dest *Hoge) error 355 | 356 | // HogePropertyInfo stores property information. 357 | type HogePropertyInfo struct { 358 | fieldName string 359 | jsonName string 360 | Encoder HogePropertyEncoder 361 | Decoder HogePropertyDecoder 362 | } 363 | 364 | // FieldName returns struct field name of property. 365 | func (info *HogePropertyInfo) FieldName() string { 366 | return info.fieldName 367 | } 368 | 369 | // JSONName returns json field name of property. 370 | func (info *HogePropertyInfo) JSONName() string { 371 | return info.jsonName 372 | } 373 | 374 | // HogeJSONBuilder convert between Hoge to HogeJSON mutually. 375 | type HogeJSONBuilder struct { 376 | _properties map[string]*HogePropertyInfo 377 | _jsonPropertyMap map[string]*HogePropertyInfo 378 | _structPropertyMap map[string]*HogePropertyInfo 379 | Hoge1 *HogePropertyInfo 380 | } 381 | 382 | // NewHogeJSONBuilder make new HogeJSONBuilder. 383 | func NewHogeJSONBuilder() *HogeJSONBuilder { 384 | jb := &HogeJSONBuilder{ 385 | _properties: map[string]*HogePropertyInfo{}, 386 | _jsonPropertyMap: map[string]*HogePropertyInfo{}, 387 | _structPropertyMap: map[string]*HogePropertyInfo{}, 388 | Hoge1: &HogePropertyInfo{ 389 | fieldName: "Hoge1", 390 | jsonName: "hoge1", 391 | Encoder: func(src *Hoge, dest *HogeJSON) error { 392 | if src == nil { 393 | return nil 394 | } 395 | dest.Hoge1 = src.Hoge1 396 | return nil 397 | }, 398 | Decoder: func(src *HogeJSON, dest *Hoge) error { 399 | if src == nil { 400 | return nil 401 | } 402 | dest.Hoge1 = src.Hoge1 403 | return nil 404 | }, 405 | }, 406 | } 407 | jb._structPropertyMap["Hoge1"] = jb.Hoge1 408 | jb._jsonPropertyMap["hoge1"] = jb.Hoge1 409 | return jb 410 | } 411 | 412 | // Properties returns all properties on HogeJSONBuilder. 413 | func (b *HogeJSONBuilder) Properties() []*HogePropertyInfo { 414 | return []*HogePropertyInfo{ 415 | b.Hoge1, 416 | } 417 | } 418 | 419 | // AddAll adds all property to HogeJSONBuilder. 420 | func (b *HogeJSONBuilder) AddAll() *HogeJSONBuilder { 421 | b._properties["Hoge1"] = b.Hoge1 422 | return b 423 | } 424 | 425 | // Add specified property to HogeJSONBuilder. 426 | func (b *HogeJSONBuilder) Add(info *HogePropertyInfo) *HogeJSONBuilder { 427 | b._properties[info.fieldName] = info 428 | return b 429 | } 430 | 431 | // AddByJSONNames add properties to HogeJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 432 | func (b *HogeJSONBuilder) AddByJSONNames(names ...string) *HogeJSONBuilder { 433 | for _, name := range names { 434 | info := b._jsonPropertyMap[name] 435 | if info == nil { 436 | continue 437 | } 438 | b._properties[info.fieldName] = info 439 | } 440 | return b 441 | } 442 | 443 | // AddByNames add properties to HogeJSONBuilder by struct property name. if name is not in the builder, it will ignore. 444 | func (b *HogeJSONBuilder) AddByNames(names ...string) *HogeJSONBuilder { 445 | for _, name := range names { 446 | info := b._structPropertyMap[name] 447 | if info == nil { 448 | continue 449 | } 450 | b._properties[info.fieldName] = info 451 | } 452 | return b 453 | } 454 | 455 | // Remove specified property to HogeJSONBuilder. 456 | func (b *HogeJSONBuilder) Remove(info *HogePropertyInfo) *HogeJSONBuilder { 457 | delete(b._properties, info.fieldName) 458 | return b 459 | } 460 | 461 | // RemoveByJSONNames remove properties to HogeJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 462 | func (b *HogeJSONBuilder) RemoveByJSONNames(names ...string) *HogeJSONBuilder { 463 | 464 | for _, name := range names { 465 | info := b._jsonPropertyMap[name] 466 | if info == nil { 467 | continue 468 | } 469 | delete(b._properties, info.fieldName) 470 | } 471 | return b 472 | } 473 | 474 | // RemoveByNames remove properties to HogeJSONBuilder by struct property name. if name is not in the builder, it will ignore. 475 | func (b *HogeJSONBuilder) RemoveByNames(names ...string) *HogeJSONBuilder { 476 | for _, name := range names { 477 | info := b._structPropertyMap[name] 478 | if info == nil { 479 | continue 480 | } 481 | delete(b._properties, info.fieldName) 482 | } 483 | return b 484 | } 485 | 486 | // Convert specified non-JSON object to JSON object. 487 | func (b *HogeJSONBuilder) Convert(orig *Hoge) (*HogeJSON, error) { 488 | if orig == nil { 489 | return nil, nil 490 | } 491 | ret := &HogeJSON{} 492 | 493 | for _, info := range b._properties { 494 | if err := info.Encoder(orig, ret); err != nil { 495 | return nil, err 496 | } 497 | } 498 | 499 | return ret, nil 500 | } 501 | 502 | // ConvertList specified non-JSON slice to JSONList. 503 | func (b *HogeJSONBuilder) ConvertList(orig []*Hoge) (HogeJSONList, error) { 504 | if orig == nil { 505 | return nil, nil 506 | } 507 | 508 | list := make(HogeJSONList, len(orig)) 509 | for idx, or := range orig { 510 | json, err := b.Convert(or) 511 | if err != nil { 512 | return nil, err 513 | } 514 | list[idx] = json 515 | } 516 | 517 | return list, nil 518 | } 519 | 520 | // Convert specified JSON object to non-JSON object. 521 | func (orig *HogeJSON) Convert() (*Hoge, error) { 522 | ret := &Hoge{} 523 | 524 | b := NewHogeJSONBuilder().AddAll() 525 | for _, info := range b._properties { 526 | if err := info.Decoder(orig, ret); err != nil { 527 | return nil, err 528 | } 529 | } 530 | 531 | return ret, nil 532 | } 533 | 534 | // Convert specified JSONList to non-JSON slice. 535 | func (jsonList HogeJSONList) Convert() ([]*Hoge, error) { 536 | orig := ([]*HogeJSON)(jsonList) 537 | 538 | list := make([]*Hoge, len(orig)) 539 | for idx, or := range orig { 540 | obj, err := or.Convert() 541 | if err != nil { 542 | return nil, err 543 | } 544 | list[idx] = obj 545 | } 546 | 547 | return list, nil 548 | } 549 | 550 | // Marshal non-JSON object to JSON string. 551 | func (b *HogeJSONBuilder) Marshal(orig *Hoge) ([]byte, error) { 552 | ret, err := b.Convert(orig) 553 | if err != nil { 554 | return nil, err 555 | } 556 | return json.Marshal(ret) 557 | } 558 | 559 | // FugaJSON is jsonized struct for Fuga. 560 | type FugaJSON struct { 561 | Fuga1 string `json:"fuga1,omitempty"` 562 | } 563 | 564 | // FugaJSONList is synonym about []*FugaJSON. 565 | type FugaJSONList []*FugaJSON 566 | 567 | // FugaPropertyEncoder is property encoder for [1]sJSON. 568 | type FugaPropertyEncoder func(src *Fuga, dest *FugaJSON) error 569 | 570 | // FugaPropertyDecoder is property decoder for [1]sJSON. 571 | type FugaPropertyDecoder func(src *FugaJSON, dest *Fuga) error 572 | 573 | // FugaPropertyInfo stores property information. 574 | type FugaPropertyInfo struct { 575 | fieldName string 576 | jsonName string 577 | Encoder FugaPropertyEncoder 578 | Decoder FugaPropertyDecoder 579 | } 580 | 581 | // FieldName returns struct field name of property. 582 | func (info *FugaPropertyInfo) FieldName() string { 583 | return info.fieldName 584 | } 585 | 586 | // JSONName returns json field name of property. 587 | func (info *FugaPropertyInfo) JSONName() string { 588 | return info.jsonName 589 | } 590 | 591 | // FugaJSONBuilder convert between Fuga to FugaJSON mutually. 592 | type FugaJSONBuilder struct { 593 | _properties map[string]*FugaPropertyInfo 594 | _jsonPropertyMap map[string]*FugaPropertyInfo 595 | _structPropertyMap map[string]*FugaPropertyInfo 596 | Fuga1 *FugaPropertyInfo 597 | } 598 | 599 | // NewFugaJSONBuilder make new FugaJSONBuilder. 600 | func NewFugaJSONBuilder() *FugaJSONBuilder { 601 | jb := &FugaJSONBuilder{ 602 | _properties: map[string]*FugaPropertyInfo{}, 603 | _jsonPropertyMap: map[string]*FugaPropertyInfo{}, 604 | _structPropertyMap: map[string]*FugaPropertyInfo{}, 605 | Fuga1: &FugaPropertyInfo{ 606 | fieldName: "Fuga1", 607 | jsonName: "fuga1", 608 | Encoder: func(src *Fuga, dest *FugaJSON) error { 609 | if src == nil { 610 | return nil 611 | } 612 | dest.Fuga1 = src.Fuga1 613 | return nil 614 | }, 615 | Decoder: func(src *FugaJSON, dest *Fuga) error { 616 | if src == nil { 617 | return nil 618 | } 619 | dest.Fuga1 = src.Fuga1 620 | return nil 621 | }, 622 | }, 623 | } 624 | jb._structPropertyMap["Fuga1"] = jb.Fuga1 625 | jb._jsonPropertyMap["fuga1"] = jb.Fuga1 626 | return jb 627 | } 628 | 629 | // Properties returns all properties on FugaJSONBuilder. 630 | func (b *FugaJSONBuilder) Properties() []*FugaPropertyInfo { 631 | return []*FugaPropertyInfo{ 632 | b.Fuga1, 633 | } 634 | } 635 | 636 | // AddAll adds all property to FugaJSONBuilder. 637 | func (b *FugaJSONBuilder) AddAll() *FugaJSONBuilder { 638 | b._properties["Fuga1"] = b.Fuga1 639 | return b 640 | } 641 | 642 | // Add specified property to FugaJSONBuilder. 643 | func (b *FugaJSONBuilder) Add(info *FugaPropertyInfo) *FugaJSONBuilder { 644 | b._properties[info.fieldName] = info 645 | return b 646 | } 647 | 648 | // AddByJSONNames add properties to FugaJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 649 | func (b *FugaJSONBuilder) AddByJSONNames(names ...string) *FugaJSONBuilder { 650 | for _, name := range names { 651 | info := b._jsonPropertyMap[name] 652 | if info == nil { 653 | continue 654 | } 655 | b._properties[info.fieldName] = info 656 | } 657 | return b 658 | } 659 | 660 | // AddByNames add properties to FugaJSONBuilder by struct property name. if name is not in the builder, it will ignore. 661 | func (b *FugaJSONBuilder) AddByNames(names ...string) *FugaJSONBuilder { 662 | for _, name := range names { 663 | info := b._structPropertyMap[name] 664 | if info == nil { 665 | continue 666 | } 667 | b._properties[info.fieldName] = info 668 | } 669 | return b 670 | } 671 | 672 | // Remove specified property to FugaJSONBuilder. 673 | func (b *FugaJSONBuilder) Remove(info *FugaPropertyInfo) *FugaJSONBuilder { 674 | delete(b._properties, info.fieldName) 675 | return b 676 | } 677 | 678 | // RemoveByJSONNames remove properties to FugaJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 679 | func (b *FugaJSONBuilder) RemoveByJSONNames(names ...string) *FugaJSONBuilder { 680 | 681 | for _, name := range names { 682 | info := b._jsonPropertyMap[name] 683 | if info == nil { 684 | continue 685 | } 686 | delete(b._properties, info.fieldName) 687 | } 688 | return b 689 | } 690 | 691 | // RemoveByNames remove properties to FugaJSONBuilder by struct property name. if name is not in the builder, it will ignore. 692 | func (b *FugaJSONBuilder) RemoveByNames(names ...string) *FugaJSONBuilder { 693 | for _, name := range names { 694 | info := b._structPropertyMap[name] 695 | if info == nil { 696 | continue 697 | } 698 | delete(b._properties, info.fieldName) 699 | } 700 | return b 701 | } 702 | 703 | // Convert specified non-JSON object to JSON object. 704 | func (b *FugaJSONBuilder) Convert(orig *Fuga) (*FugaJSON, error) { 705 | if orig == nil { 706 | return nil, nil 707 | } 708 | ret := &FugaJSON{} 709 | 710 | for _, info := range b._properties { 711 | if err := info.Encoder(orig, ret); err != nil { 712 | return nil, err 713 | } 714 | } 715 | 716 | return ret, nil 717 | } 718 | 719 | // ConvertList specified non-JSON slice to JSONList. 720 | func (b *FugaJSONBuilder) ConvertList(orig []*Fuga) (FugaJSONList, error) { 721 | if orig == nil { 722 | return nil, nil 723 | } 724 | 725 | list := make(FugaJSONList, len(orig)) 726 | for idx, or := range orig { 727 | json, err := b.Convert(or) 728 | if err != nil { 729 | return nil, err 730 | } 731 | list[idx] = json 732 | } 733 | 734 | return list, nil 735 | } 736 | 737 | // Convert specified JSON object to non-JSON object. 738 | func (orig *FugaJSON) Convert() (*Fuga, error) { 739 | ret := &Fuga{} 740 | 741 | b := NewFugaJSONBuilder().AddAll() 742 | for _, info := range b._properties { 743 | if err := info.Decoder(orig, ret); err != nil { 744 | return nil, err 745 | } 746 | } 747 | 748 | return ret, nil 749 | } 750 | 751 | // Convert specified JSONList to non-JSON slice. 752 | func (jsonList FugaJSONList) Convert() ([]*Fuga, error) { 753 | orig := ([]*FugaJSON)(jsonList) 754 | 755 | list := make([]*Fuga, len(orig)) 756 | for idx, or := range orig { 757 | obj, err := or.Convert() 758 | if err != nil { 759 | return nil, err 760 | } 761 | list[idx] = obj 762 | } 763 | 764 | return list, nil 765 | } 766 | 767 | // Marshal non-JSON object to JSON string. 768 | func (b *FugaJSONBuilder) Marshal(orig *Fuga) ([]byte, error) { 769 | ret, err := b.Convert(orig) 770 | if err != nil { 771 | return nil, err 772 | } 773 | return json.Marshal(ret) 774 | } 775 | -------------------------------------------------------------------------------- /misc/fixture/j/model_test.go: -------------------------------------------------------------------------------- 1 | package j 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | ) 7 | 8 | func TestModel(t *testing.T) { 9 | obj := &Foo{ 10 | Tmp: &Temp{"a"}, 11 | Bar: Bar{"b"}, 12 | Buzz: &Buzz{"c"}, 13 | Hoge: Hoge{"d"}, 14 | Fuga: &Fuga{"d"}, 15 | } 16 | jsonObj, err := NewFooJSONBuilder().AddAll().Convert(obj) 17 | if err != nil { 18 | t.Fatal(err.Error()) 19 | } 20 | b, err := json.Marshal(jsonObj) 21 | if err != nil { 22 | t.Fatal(err.Error()) 23 | } 24 | if string(b) != `{"tmp":{"Temp1":"a"},"Bar1":"b","Buzz1":"c","hoge1":"d","fuga1":"d"}` { 25 | t.Errorf("not expected: %s", string(b)) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /misc/fixture/k/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -output model_json.go . 2 | 3 | package k 4 | 5 | import ( 6 | o1 "github.com/favclip/jwg/misc/other/v1" 7 | o2 "github.com/favclip/jwg/misc/other/v2" 8 | ) 9 | 10 | // +jwg 11 | type Foo struct { 12 | Test *o1.Test 13 | } 14 | 15 | // +jwg 16 | type Bar struct { 17 | Tests []*o2.Test 18 | } 19 | -------------------------------------------------------------------------------- /misc/fixture/k/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -output misc/fixture/k/model_json.go misc/fixture/k; DO NOT EDIT 2 | 3 | package k 4 | 5 | import ( 6 | "encoding/json" 7 | o1 "github.com/favclip/jwg/misc/other/v1" 8 | o2 "github.com/favclip/jwg/misc/other/v2" 9 | ) 10 | 11 | // FooJSON is jsonized struct for Foo. 12 | type FooJSON struct { 13 | Test *o1.Test `json:"test,omitempty"` 14 | } 15 | 16 | // FooJSONList is synonym about []*FooJSON. 17 | type FooJSONList []*FooJSON 18 | 19 | // FooPropertyEncoder is property encoder for [1]sJSON. 20 | type FooPropertyEncoder func(src *Foo, dest *FooJSON) error 21 | 22 | // FooPropertyDecoder is property decoder for [1]sJSON. 23 | type FooPropertyDecoder func(src *FooJSON, dest *Foo) error 24 | 25 | // FooPropertyInfo stores property information. 26 | type FooPropertyInfo struct { 27 | fieldName string 28 | jsonName string 29 | Encoder FooPropertyEncoder 30 | Decoder FooPropertyDecoder 31 | } 32 | 33 | // FieldName returns struct field name of property. 34 | func (info *FooPropertyInfo) FieldName() string { 35 | return info.fieldName 36 | } 37 | 38 | // JSONName returns json field name of property. 39 | func (info *FooPropertyInfo) JSONName() string { 40 | return info.jsonName 41 | } 42 | 43 | // FooJSONBuilder convert between Foo to FooJSON mutually. 44 | type FooJSONBuilder struct { 45 | _properties map[string]*FooPropertyInfo 46 | _jsonPropertyMap map[string]*FooPropertyInfo 47 | _structPropertyMap map[string]*FooPropertyInfo 48 | Test *FooPropertyInfo 49 | } 50 | 51 | // NewFooJSONBuilder make new FooJSONBuilder. 52 | func NewFooJSONBuilder() *FooJSONBuilder { 53 | jb := &FooJSONBuilder{ 54 | _properties: map[string]*FooPropertyInfo{}, 55 | _jsonPropertyMap: map[string]*FooPropertyInfo{}, 56 | _structPropertyMap: map[string]*FooPropertyInfo{}, 57 | Test: &FooPropertyInfo{ 58 | fieldName: "Test", 59 | jsonName: "test", 60 | Encoder: func(src *Foo, dest *FooJSON) error { 61 | if src == nil { 62 | return nil 63 | } 64 | dest.Test = src.Test 65 | return nil 66 | }, 67 | Decoder: func(src *FooJSON, dest *Foo) error { 68 | if src == nil { 69 | return nil 70 | } 71 | dest.Test = src.Test 72 | return nil 73 | }, 74 | }, 75 | } 76 | jb._structPropertyMap["Test"] = jb.Test 77 | jb._jsonPropertyMap["test"] = jb.Test 78 | return jb 79 | } 80 | 81 | // Properties returns all properties on FooJSONBuilder. 82 | func (b *FooJSONBuilder) Properties() []*FooPropertyInfo { 83 | return []*FooPropertyInfo{ 84 | b.Test, 85 | } 86 | } 87 | 88 | // AddAll adds all property to FooJSONBuilder. 89 | func (b *FooJSONBuilder) AddAll() *FooJSONBuilder { 90 | b._properties["Test"] = b.Test 91 | return b 92 | } 93 | 94 | // Add specified property to FooJSONBuilder. 95 | func (b *FooJSONBuilder) Add(info *FooPropertyInfo) *FooJSONBuilder { 96 | b._properties[info.fieldName] = info 97 | return b 98 | } 99 | 100 | // AddByJSONNames add properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 101 | func (b *FooJSONBuilder) AddByJSONNames(names ...string) *FooJSONBuilder { 102 | for _, name := range names { 103 | info := b._jsonPropertyMap[name] 104 | if info == nil { 105 | continue 106 | } 107 | b._properties[info.fieldName] = info 108 | } 109 | return b 110 | } 111 | 112 | // AddByNames add properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore. 113 | func (b *FooJSONBuilder) AddByNames(names ...string) *FooJSONBuilder { 114 | for _, name := range names { 115 | info := b._structPropertyMap[name] 116 | if info == nil { 117 | continue 118 | } 119 | b._properties[info.fieldName] = info 120 | } 121 | return b 122 | } 123 | 124 | // Remove specified property to FooJSONBuilder. 125 | func (b *FooJSONBuilder) Remove(info *FooPropertyInfo) *FooJSONBuilder { 126 | delete(b._properties, info.fieldName) 127 | return b 128 | } 129 | 130 | // RemoveByJSONNames remove properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 131 | func (b *FooJSONBuilder) RemoveByJSONNames(names ...string) *FooJSONBuilder { 132 | 133 | for _, name := range names { 134 | info := b._jsonPropertyMap[name] 135 | if info == nil { 136 | continue 137 | } 138 | delete(b._properties, info.fieldName) 139 | } 140 | return b 141 | } 142 | 143 | // RemoveByNames remove properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore. 144 | func (b *FooJSONBuilder) RemoveByNames(names ...string) *FooJSONBuilder { 145 | for _, name := range names { 146 | info := b._structPropertyMap[name] 147 | if info == nil { 148 | continue 149 | } 150 | delete(b._properties, info.fieldName) 151 | } 152 | return b 153 | } 154 | 155 | // Convert specified non-JSON object to JSON object. 156 | func (b *FooJSONBuilder) Convert(orig *Foo) (*FooJSON, error) { 157 | if orig == nil { 158 | return nil, nil 159 | } 160 | ret := &FooJSON{} 161 | 162 | for _, info := range b._properties { 163 | if err := info.Encoder(orig, ret); err != nil { 164 | return nil, err 165 | } 166 | } 167 | 168 | return ret, nil 169 | } 170 | 171 | // ConvertList specified non-JSON slice to JSONList. 172 | func (b *FooJSONBuilder) ConvertList(orig []*Foo) (FooJSONList, error) { 173 | if orig == nil { 174 | return nil, nil 175 | } 176 | 177 | list := make(FooJSONList, len(orig)) 178 | for idx, or := range orig { 179 | json, err := b.Convert(or) 180 | if err != nil { 181 | return nil, err 182 | } 183 | list[idx] = json 184 | } 185 | 186 | return list, nil 187 | } 188 | 189 | // Convert specified JSON object to non-JSON object. 190 | func (orig *FooJSON) Convert() (*Foo, error) { 191 | ret := &Foo{} 192 | 193 | b := NewFooJSONBuilder().AddAll() 194 | for _, info := range b._properties { 195 | if err := info.Decoder(orig, ret); err != nil { 196 | return nil, err 197 | } 198 | } 199 | 200 | return ret, nil 201 | } 202 | 203 | // Convert specified JSONList to non-JSON slice. 204 | func (jsonList FooJSONList) Convert() ([]*Foo, error) { 205 | orig := ([]*FooJSON)(jsonList) 206 | 207 | list := make([]*Foo, len(orig)) 208 | for idx, or := range orig { 209 | obj, err := or.Convert() 210 | if err != nil { 211 | return nil, err 212 | } 213 | list[idx] = obj 214 | } 215 | 216 | return list, nil 217 | } 218 | 219 | // Marshal non-JSON object to JSON string. 220 | func (b *FooJSONBuilder) Marshal(orig *Foo) ([]byte, error) { 221 | ret, err := b.Convert(orig) 222 | if err != nil { 223 | return nil, err 224 | } 225 | return json.Marshal(ret) 226 | } 227 | 228 | // BarJSON is jsonized struct for Bar. 229 | type BarJSON struct { 230 | Tests []*o2.Test `json:"tests,omitempty"` 231 | } 232 | 233 | // BarJSONList is synonym about []*BarJSON. 234 | type BarJSONList []*BarJSON 235 | 236 | // BarPropertyEncoder is property encoder for [1]sJSON. 237 | type BarPropertyEncoder func(src *Bar, dest *BarJSON) error 238 | 239 | // BarPropertyDecoder is property decoder for [1]sJSON. 240 | type BarPropertyDecoder func(src *BarJSON, dest *Bar) error 241 | 242 | // BarPropertyInfo stores property information. 243 | type BarPropertyInfo struct { 244 | fieldName string 245 | jsonName string 246 | Encoder BarPropertyEncoder 247 | Decoder BarPropertyDecoder 248 | } 249 | 250 | // FieldName returns struct field name of property. 251 | func (info *BarPropertyInfo) FieldName() string { 252 | return info.fieldName 253 | } 254 | 255 | // JSONName returns json field name of property. 256 | func (info *BarPropertyInfo) JSONName() string { 257 | return info.jsonName 258 | } 259 | 260 | // BarJSONBuilder convert between Bar to BarJSON mutually. 261 | type BarJSONBuilder struct { 262 | _properties map[string]*BarPropertyInfo 263 | _jsonPropertyMap map[string]*BarPropertyInfo 264 | _structPropertyMap map[string]*BarPropertyInfo 265 | Tests *BarPropertyInfo 266 | } 267 | 268 | // NewBarJSONBuilder make new BarJSONBuilder. 269 | func NewBarJSONBuilder() *BarJSONBuilder { 270 | jb := &BarJSONBuilder{ 271 | _properties: map[string]*BarPropertyInfo{}, 272 | _jsonPropertyMap: map[string]*BarPropertyInfo{}, 273 | _structPropertyMap: map[string]*BarPropertyInfo{}, 274 | Tests: &BarPropertyInfo{ 275 | fieldName: "Tests", 276 | jsonName: "tests", 277 | Encoder: func(src *Bar, dest *BarJSON) error { 278 | if src == nil { 279 | return nil 280 | } 281 | dest.Tests = src.Tests 282 | return nil 283 | }, 284 | Decoder: func(src *BarJSON, dest *Bar) error { 285 | if src == nil { 286 | return nil 287 | } 288 | dest.Tests = src.Tests 289 | return nil 290 | }, 291 | }, 292 | } 293 | jb._structPropertyMap["Tests"] = jb.Tests 294 | jb._jsonPropertyMap["tests"] = jb.Tests 295 | return jb 296 | } 297 | 298 | // Properties returns all properties on BarJSONBuilder. 299 | func (b *BarJSONBuilder) Properties() []*BarPropertyInfo { 300 | return []*BarPropertyInfo{ 301 | b.Tests, 302 | } 303 | } 304 | 305 | // AddAll adds all property to BarJSONBuilder. 306 | func (b *BarJSONBuilder) AddAll() *BarJSONBuilder { 307 | b._properties["Tests"] = b.Tests 308 | return b 309 | } 310 | 311 | // Add specified property to BarJSONBuilder. 312 | func (b *BarJSONBuilder) Add(info *BarPropertyInfo) *BarJSONBuilder { 313 | b._properties[info.fieldName] = info 314 | return b 315 | } 316 | 317 | // AddByJSONNames add properties to BarJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 318 | func (b *BarJSONBuilder) AddByJSONNames(names ...string) *BarJSONBuilder { 319 | for _, name := range names { 320 | info := b._jsonPropertyMap[name] 321 | if info == nil { 322 | continue 323 | } 324 | b._properties[info.fieldName] = info 325 | } 326 | return b 327 | } 328 | 329 | // AddByNames add properties to BarJSONBuilder by struct property name. if name is not in the builder, it will ignore. 330 | func (b *BarJSONBuilder) AddByNames(names ...string) *BarJSONBuilder { 331 | for _, name := range names { 332 | info := b._structPropertyMap[name] 333 | if info == nil { 334 | continue 335 | } 336 | b._properties[info.fieldName] = info 337 | } 338 | return b 339 | } 340 | 341 | // Remove specified property to BarJSONBuilder. 342 | func (b *BarJSONBuilder) Remove(info *BarPropertyInfo) *BarJSONBuilder { 343 | delete(b._properties, info.fieldName) 344 | return b 345 | } 346 | 347 | // RemoveByJSONNames remove properties to BarJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 348 | func (b *BarJSONBuilder) RemoveByJSONNames(names ...string) *BarJSONBuilder { 349 | 350 | for _, name := range names { 351 | info := b._jsonPropertyMap[name] 352 | if info == nil { 353 | continue 354 | } 355 | delete(b._properties, info.fieldName) 356 | } 357 | return b 358 | } 359 | 360 | // RemoveByNames remove properties to BarJSONBuilder by struct property name. if name is not in the builder, it will ignore. 361 | func (b *BarJSONBuilder) RemoveByNames(names ...string) *BarJSONBuilder { 362 | for _, name := range names { 363 | info := b._structPropertyMap[name] 364 | if info == nil { 365 | continue 366 | } 367 | delete(b._properties, info.fieldName) 368 | } 369 | return b 370 | } 371 | 372 | // Convert specified non-JSON object to JSON object. 373 | func (b *BarJSONBuilder) Convert(orig *Bar) (*BarJSON, error) { 374 | if orig == nil { 375 | return nil, nil 376 | } 377 | ret := &BarJSON{} 378 | 379 | for _, info := range b._properties { 380 | if err := info.Encoder(orig, ret); err != nil { 381 | return nil, err 382 | } 383 | } 384 | 385 | return ret, nil 386 | } 387 | 388 | // ConvertList specified non-JSON slice to JSONList. 389 | func (b *BarJSONBuilder) ConvertList(orig []*Bar) (BarJSONList, error) { 390 | if orig == nil { 391 | return nil, nil 392 | } 393 | 394 | list := make(BarJSONList, len(orig)) 395 | for idx, or := range orig { 396 | json, err := b.Convert(or) 397 | if err != nil { 398 | return nil, err 399 | } 400 | list[idx] = json 401 | } 402 | 403 | return list, nil 404 | } 405 | 406 | // Convert specified JSON object to non-JSON object. 407 | func (orig *BarJSON) Convert() (*Bar, error) { 408 | ret := &Bar{} 409 | 410 | b := NewBarJSONBuilder().AddAll() 411 | for _, info := range b._properties { 412 | if err := info.Decoder(orig, ret); err != nil { 413 | return nil, err 414 | } 415 | } 416 | 417 | return ret, nil 418 | } 419 | 420 | // Convert specified JSONList to non-JSON slice. 421 | func (jsonList BarJSONList) Convert() ([]*Bar, error) { 422 | orig := ([]*BarJSON)(jsonList) 423 | 424 | list := make([]*Bar, len(orig)) 425 | for idx, or := range orig { 426 | obj, err := or.Convert() 427 | if err != nil { 428 | return nil, err 429 | } 430 | list[idx] = obj 431 | } 432 | 433 | return list, nil 434 | } 435 | 436 | // Marshal non-JSON object to JSON string. 437 | func (b *BarJSONBuilder) Marshal(orig *Bar) ([]byte, error) { 438 | ret, err := b.Convert(orig) 439 | if err != nil { 440 | return nil, err 441 | } 442 | return json.Marshal(ret) 443 | } 444 | -------------------------------------------------------------------------------- /misc/fixture/l/model.go: -------------------------------------------------------------------------------- 1 | package l 2 | 3 | // test for struct with json tag and others 4 | 5 | type Sample struct { 6 | A string `json:"-"` 7 | B string `json:",omitempty" swagger:",enum=ok|ng"` 8 | C string `swagger:",enum=ok|ng"` 9 | D string `swagger:",enum=ok|ng" includes:"test"` 10 | E string `swagger:",enum=ok|ng" excludes:"test"` 11 | } 12 | -------------------------------------------------------------------------------- /misc/fixture/l/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/l/model_json.go -transcripttag swagger,includes misc/fixture/l; DO NOT EDIT 2 | 3 | package l 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | B string `json:"b,omitempty" swagger:",enum=ok|ng"` 12 | C string `json:"c,omitempty" swagger:",enum=ok|ng"` 13 | D string `json:"d,omitempty" swagger:",enum=ok|ng" includes:"test"` 14 | E string `json:"e,omitempty" swagger:",enum=ok|ng"` 15 | } 16 | 17 | // SampleJSONList is synonym about []*SampleJSON. 18 | type SampleJSONList []*SampleJSON 19 | 20 | // SamplePropertyEncoder is property encoder for [1]sJSON. 21 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 22 | 23 | // SamplePropertyDecoder is property decoder for [1]sJSON. 24 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 25 | 26 | // SamplePropertyInfo stores property information. 27 | type SamplePropertyInfo struct { 28 | fieldName string 29 | jsonName string 30 | Encoder SamplePropertyEncoder 31 | Decoder SamplePropertyDecoder 32 | } 33 | 34 | // FieldName returns struct field name of property. 35 | func (info *SamplePropertyInfo) FieldName() string { 36 | return info.fieldName 37 | } 38 | 39 | // JSONName returns json field name of property. 40 | func (info *SamplePropertyInfo) JSONName() string { 41 | return info.jsonName 42 | } 43 | 44 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 45 | type SampleJSONBuilder struct { 46 | _properties map[string]*SamplePropertyInfo 47 | _jsonPropertyMap map[string]*SamplePropertyInfo 48 | _structPropertyMap map[string]*SamplePropertyInfo 49 | B *SamplePropertyInfo 50 | C *SamplePropertyInfo 51 | D *SamplePropertyInfo 52 | E *SamplePropertyInfo 53 | } 54 | 55 | // NewSampleJSONBuilder make new SampleJSONBuilder. 56 | func NewSampleJSONBuilder() *SampleJSONBuilder { 57 | jb := &SampleJSONBuilder{ 58 | _properties: map[string]*SamplePropertyInfo{}, 59 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 60 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 61 | B: &SamplePropertyInfo{ 62 | fieldName: "B", 63 | jsonName: "b", 64 | Encoder: func(src *Sample, dest *SampleJSON) error { 65 | if src == nil { 66 | return nil 67 | } 68 | dest.B = src.B 69 | return nil 70 | }, 71 | Decoder: func(src *SampleJSON, dest *Sample) error { 72 | if src == nil { 73 | return nil 74 | } 75 | dest.B = src.B 76 | return nil 77 | }, 78 | }, 79 | C: &SamplePropertyInfo{ 80 | fieldName: "C", 81 | jsonName: "c", 82 | Encoder: func(src *Sample, dest *SampleJSON) error { 83 | if src == nil { 84 | return nil 85 | } 86 | dest.C = src.C 87 | return nil 88 | }, 89 | Decoder: func(src *SampleJSON, dest *Sample) error { 90 | if src == nil { 91 | return nil 92 | } 93 | dest.C = src.C 94 | return nil 95 | }, 96 | }, 97 | D: &SamplePropertyInfo{ 98 | fieldName: "D", 99 | jsonName: "d", 100 | Encoder: func(src *Sample, dest *SampleJSON) error { 101 | if src == nil { 102 | return nil 103 | } 104 | dest.D = src.D 105 | return nil 106 | }, 107 | Decoder: func(src *SampleJSON, dest *Sample) error { 108 | if src == nil { 109 | return nil 110 | } 111 | dest.D = src.D 112 | return nil 113 | }, 114 | }, 115 | E: &SamplePropertyInfo{ 116 | fieldName: "E", 117 | jsonName: "e", 118 | Encoder: func(src *Sample, dest *SampleJSON) error { 119 | if src == nil { 120 | return nil 121 | } 122 | dest.E = src.E 123 | return nil 124 | }, 125 | Decoder: func(src *SampleJSON, dest *Sample) error { 126 | if src == nil { 127 | return nil 128 | } 129 | dest.E = src.E 130 | return nil 131 | }, 132 | }, 133 | } 134 | jb._structPropertyMap["B"] = jb.B 135 | jb._jsonPropertyMap["b"] = jb.B 136 | jb._structPropertyMap["C"] = jb.C 137 | jb._jsonPropertyMap["c"] = jb.C 138 | jb._structPropertyMap["D"] = jb.D 139 | jb._jsonPropertyMap["d"] = jb.D 140 | jb._structPropertyMap["E"] = jb.E 141 | jb._jsonPropertyMap["e"] = jb.E 142 | return jb 143 | } 144 | 145 | // Properties returns all properties on SampleJSONBuilder. 146 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 147 | return []*SamplePropertyInfo{ 148 | b.B, 149 | b.C, 150 | b.D, 151 | b.E, 152 | } 153 | } 154 | 155 | // AddAll adds all property to SampleJSONBuilder. 156 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 157 | b._properties["B"] = b.B 158 | b._properties["C"] = b.C 159 | b._properties["D"] = b.D 160 | b._properties["E"] = b.E 161 | return b 162 | } 163 | 164 | // Add specified property to SampleJSONBuilder. 165 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 166 | for _, info := range infos { 167 | b._properties[info.fieldName] = info 168 | } 169 | return b 170 | } 171 | 172 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 173 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 174 | for _, name := range names { 175 | info := b._jsonPropertyMap[name] 176 | if info == nil { 177 | continue 178 | } 179 | b._properties[info.fieldName] = info 180 | } 181 | return b 182 | } 183 | 184 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 185 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 186 | for _, name := range names { 187 | info := b._structPropertyMap[name] 188 | if info == nil { 189 | continue 190 | } 191 | b._properties[info.fieldName] = info 192 | } 193 | return b 194 | } 195 | 196 | // Remove specified property to SampleJSONBuilder. 197 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 198 | for _, info := range infos { 199 | delete(b._properties, info.fieldName) 200 | } 201 | return b 202 | } 203 | 204 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 205 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 206 | 207 | for _, name := range names { 208 | info := b._jsonPropertyMap[name] 209 | if info == nil { 210 | continue 211 | } 212 | delete(b._properties, info.fieldName) 213 | } 214 | return b 215 | } 216 | 217 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 218 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 219 | for _, name := range names { 220 | info := b._structPropertyMap[name] 221 | if info == nil { 222 | continue 223 | } 224 | delete(b._properties, info.fieldName) 225 | } 226 | return b 227 | } 228 | 229 | // Convert specified non-JSON object to JSON object. 230 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 231 | if orig == nil { 232 | return nil, nil 233 | } 234 | ret := &SampleJSON{} 235 | 236 | for _, info := range b._properties { 237 | if err := info.Encoder(orig, ret); err != nil { 238 | return nil, err 239 | } 240 | } 241 | 242 | return ret, nil 243 | } 244 | 245 | // ConvertList specified non-JSON slice to JSONList. 246 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 247 | if orig == nil { 248 | return nil, nil 249 | } 250 | 251 | list := make(SampleJSONList, len(orig)) 252 | for idx, or := range orig { 253 | json, err := b.Convert(or) 254 | if err != nil { 255 | return nil, err 256 | } 257 | list[idx] = json 258 | } 259 | 260 | return list, nil 261 | } 262 | 263 | // Convert specified JSON object to non-JSON object. 264 | func (orig *SampleJSON) Convert() (*Sample, error) { 265 | ret := &Sample{} 266 | 267 | b := NewSampleJSONBuilder().AddAll() 268 | for _, info := range b._properties { 269 | if err := info.Decoder(orig, ret); err != nil { 270 | return nil, err 271 | } 272 | } 273 | 274 | return ret, nil 275 | } 276 | 277 | // Convert specified JSONList to non-JSON slice. 278 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 279 | orig := ([]*SampleJSON)(jsonList) 280 | 281 | list := make([]*Sample, len(orig)) 282 | for idx, or := range orig { 283 | obj, err := or.Convert() 284 | if err != nil { 285 | return nil, err 286 | } 287 | list[idx] = obj 288 | } 289 | 290 | return list, nil 291 | } 292 | 293 | // Marshal non-JSON object to JSON string. 294 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 295 | ret, err := b.Convert(orig) 296 | if err != nil { 297 | return nil, err 298 | } 299 | return json.Marshal(ret) 300 | } 301 | -------------------------------------------------------------------------------- /misc/fixture/m/model.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | // test for struct with shouldemit json tag 4 | 5 | type Sample struct { 6 | A string `json:",omitempty"` 7 | B string 8 | C string `json:",shouldemit"` 9 | } 10 | -------------------------------------------------------------------------------- /misc/fixture/m/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/m/model_json.go misc/fixture/m; DO NOT EDIT 2 | 3 | package m 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"a,omitempty"` 12 | B string `json:"b,omitempty"` 13 | C string `json:"c"` 14 | } 15 | 16 | // SampleJSONList is synonym about []*SampleJSON. 17 | type SampleJSONList []*SampleJSON 18 | 19 | // SamplePropertyEncoder is property encoder for [1]sJSON. 20 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 21 | 22 | // SamplePropertyDecoder is property decoder for [1]sJSON. 23 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 24 | 25 | // SamplePropertyInfo stores property information. 26 | type SamplePropertyInfo struct { 27 | fieldName string 28 | jsonName string 29 | Encoder SamplePropertyEncoder 30 | Decoder SamplePropertyDecoder 31 | } 32 | 33 | // FieldName returns struct field name of property. 34 | func (info *SamplePropertyInfo) FieldName() string { 35 | return info.fieldName 36 | } 37 | 38 | // JSONName returns json field name of property. 39 | func (info *SamplePropertyInfo) JSONName() string { 40 | return info.jsonName 41 | } 42 | 43 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 44 | type SampleJSONBuilder struct { 45 | _properties map[string]*SamplePropertyInfo 46 | _jsonPropertyMap map[string]*SamplePropertyInfo 47 | _structPropertyMap map[string]*SamplePropertyInfo 48 | A *SamplePropertyInfo 49 | B *SamplePropertyInfo 50 | C *SamplePropertyInfo 51 | } 52 | 53 | // NewSampleJSONBuilder make new SampleJSONBuilder. 54 | func NewSampleJSONBuilder() *SampleJSONBuilder { 55 | jb := &SampleJSONBuilder{ 56 | _properties: map[string]*SamplePropertyInfo{}, 57 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 58 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 59 | A: &SamplePropertyInfo{ 60 | fieldName: "A", 61 | jsonName: "a", 62 | Encoder: func(src *Sample, dest *SampleJSON) error { 63 | if src == nil { 64 | return nil 65 | } 66 | dest.A = src.A 67 | return nil 68 | }, 69 | Decoder: func(src *SampleJSON, dest *Sample) error { 70 | if src == nil { 71 | return nil 72 | } 73 | dest.A = src.A 74 | return nil 75 | }, 76 | }, 77 | B: &SamplePropertyInfo{ 78 | fieldName: "B", 79 | jsonName: "b", 80 | Encoder: func(src *Sample, dest *SampleJSON) error { 81 | if src == nil { 82 | return nil 83 | } 84 | dest.B = src.B 85 | return nil 86 | }, 87 | Decoder: func(src *SampleJSON, dest *Sample) error { 88 | if src == nil { 89 | return nil 90 | } 91 | dest.B = src.B 92 | return nil 93 | }, 94 | }, 95 | C: &SamplePropertyInfo{ 96 | fieldName: "C", 97 | jsonName: "c", 98 | Encoder: func(src *Sample, dest *SampleJSON) error { 99 | if src == nil { 100 | return nil 101 | } 102 | dest.C = src.C 103 | return nil 104 | }, 105 | Decoder: func(src *SampleJSON, dest *Sample) error { 106 | if src == nil { 107 | return nil 108 | } 109 | dest.C = src.C 110 | return nil 111 | }, 112 | }, 113 | } 114 | jb._structPropertyMap["A"] = jb.A 115 | jb._jsonPropertyMap["a"] = jb.A 116 | jb._structPropertyMap["B"] = jb.B 117 | jb._jsonPropertyMap["b"] = jb.B 118 | jb._structPropertyMap["C"] = jb.C 119 | jb._jsonPropertyMap["c"] = jb.C 120 | return jb 121 | } 122 | 123 | // Properties returns all properties on SampleJSONBuilder. 124 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 125 | return []*SamplePropertyInfo{ 126 | b.A, 127 | b.B, 128 | b.C, 129 | } 130 | } 131 | 132 | // AddAll adds all property to SampleJSONBuilder. 133 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 134 | b._properties["A"] = b.A 135 | b._properties["B"] = b.B 136 | b._properties["C"] = b.C 137 | return b 138 | } 139 | 140 | // Add specified property to SampleJSONBuilder. 141 | func (b *SampleJSONBuilder) Add(info *SamplePropertyInfo) *SampleJSONBuilder { 142 | b._properties[info.fieldName] = info 143 | return b 144 | } 145 | 146 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 147 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 148 | for _, name := range names { 149 | info := b._jsonPropertyMap[name] 150 | if info == nil { 151 | continue 152 | } 153 | b._properties[info.fieldName] = info 154 | } 155 | return b 156 | } 157 | 158 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 159 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 160 | for _, name := range names { 161 | info := b._structPropertyMap[name] 162 | if info == nil { 163 | continue 164 | } 165 | b._properties[info.fieldName] = info 166 | } 167 | return b 168 | } 169 | 170 | // Remove specified property to SampleJSONBuilder. 171 | func (b *SampleJSONBuilder) Remove(info *SamplePropertyInfo) *SampleJSONBuilder { 172 | delete(b._properties, info.fieldName) 173 | return b 174 | } 175 | 176 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 177 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 178 | 179 | for _, name := range names { 180 | info := b._jsonPropertyMap[name] 181 | if info == nil { 182 | continue 183 | } 184 | delete(b._properties, info.fieldName) 185 | } 186 | return b 187 | } 188 | 189 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 190 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 191 | for _, name := range names { 192 | info := b._structPropertyMap[name] 193 | if info == nil { 194 | continue 195 | } 196 | delete(b._properties, info.fieldName) 197 | } 198 | return b 199 | } 200 | 201 | // Convert specified non-JSON object to JSON object. 202 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 203 | if orig == nil { 204 | return nil, nil 205 | } 206 | ret := &SampleJSON{} 207 | 208 | for _, info := range b._properties { 209 | if err := info.Encoder(orig, ret); err != nil { 210 | return nil, err 211 | } 212 | } 213 | 214 | return ret, nil 215 | } 216 | 217 | // ConvertList specified non-JSON slice to JSONList. 218 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 219 | if orig == nil { 220 | return nil, nil 221 | } 222 | 223 | list := make(SampleJSONList, len(orig)) 224 | for idx, or := range orig { 225 | json, err := b.Convert(or) 226 | if err != nil { 227 | return nil, err 228 | } 229 | list[idx] = json 230 | } 231 | 232 | return list, nil 233 | } 234 | 235 | // Convert specified JSON object to non-JSON object. 236 | func (orig *SampleJSON) Convert() (*Sample, error) { 237 | ret := &Sample{} 238 | 239 | b := NewSampleJSONBuilder().AddAll() 240 | for _, info := range b._properties { 241 | if err := info.Decoder(orig, ret); err != nil { 242 | return nil, err 243 | } 244 | } 245 | 246 | return ret, nil 247 | } 248 | 249 | // Convert specified JSONList to non-JSON slice. 250 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 251 | orig := ([]*SampleJSON)(jsonList) 252 | 253 | list := make([]*Sample, len(orig)) 254 | for idx, or := range orig { 255 | obj, err := or.Convert() 256 | if err != nil { 257 | return nil, err 258 | } 259 | list[idx] = obj 260 | } 261 | 262 | return list, nil 263 | } 264 | 265 | // Marshal non-JSON object to JSON string. 266 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 267 | ret, err := b.Convert(orig) 268 | if err != nil { 269 | return nil, err 270 | } 271 | return json.Marshal(ret) 272 | } 273 | -------------------------------------------------------------------------------- /misc/fixture/n/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -type Sample -output model_json.go -noOmitempty . 2 | 3 | package n 4 | 5 | type Sample struct { 6 | A string `json:",omitempty"` 7 | B string 8 | C string `json:",shouldemit"` 9 | } 10 | -------------------------------------------------------------------------------- /misc/fixture/n/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/n/model_json.go -noOmitempty misc/fixture/n; DO NOT EDIT 2 | 3 | package n 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"a,omitempty"` 12 | B string `json:"b"` 13 | C string `json:"c"` 14 | } 15 | 16 | // SampleJSONList is synonym about []*SampleJSON. 17 | type SampleJSONList []*SampleJSON 18 | 19 | // SamplePropertyEncoder is property encoder for [1]sJSON. 20 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 21 | 22 | // SamplePropertyDecoder is property decoder for [1]sJSON. 23 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 24 | 25 | // SamplePropertyInfo stores property information. 26 | type SamplePropertyInfo struct { 27 | fieldName string 28 | jsonName string 29 | Encoder SamplePropertyEncoder 30 | Decoder SamplePropertyDecoder 31 | } 32 | 33 | // FieldName returns struct field name of property. 34 | func (info *SamplePropertyInfo) FieldName() string { 35 | return info.fieldName 36 | } 37 | 38 | // JSONName returns json field name of property. 39 | func (info *SamplePropertyInfo) JSONName() string { 40 | return info.jsonName 41 | } 42 | 43 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 44 | type SampleJSONBuilder struct { 45 | _properties map[string]*SamplePropertyInfo 46 | _jsonPropertyMap map[string]*SamplePropertyInfo 47 | _structPropertyMap map[string]*SamplePropertyInfo 48 | A *SamplePropertyInfo 49 | B *SamplePropertyInfo 50 | C *SamplePropertyInfo 51 | } 52 | 53 | // NewSampleJSONBuilder make new SampleJSONBuilder. 54 | func NewSampleJSONBuilder() *SampleJSONBuilder { 55 | jb := &SampleJSONBuilder{ 56 | _properties: map[string]*SamplePropertyInfo{}, 57 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 58 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 59 | A: &SamplePropertyInfo{ 60 | fieldName: "A", 61 | jsonName: "a", 62 | Encoder: func(src *Sample, dest *SampleJSON) error { 63 | if src == nil { 64 | return nil 65 | } 66 | dest.A = src.A 67 | return nil 68 | }, 69 | Decoder: func(src *SampleJSON, dest *Sample) error { 70 | if src == nil { 71 | return nil 72 | } 73 | dest.A = src.A 74 | return nil 75 | }, 76 | }, 77 | B: &SamplePropertyInfo{ 78 | fieldName: "B", 79 | jsonName: "b", 80 | Encoder: func(src *Sample, dest *SampleJSON) error { 81 | if src == nil { 82 | return nil 83 | } 84 | dest.B = src.B 85 | return nil 86 | }, 87 | Decoder: func(src *SampleJSON, dest *Sample) error { 88 | if src == nil { 89 | return nil 90 | } 91 | dest.B = src.B 92 | return nil 93 | }, 94 | }, 95 | C: &SamplePropertyInfo{ 96 | fieldName: "C", 97 | jsonName: "c", 98 | Encoder: func(src *Sample, dest *SampleJSON) error { 99 | if src == nil { 100 | return nil 101 | } 102 | dest.C = src.C 103 | return nil 104 | }, 105 | Decoder: func(src *SampleJSON, dest *Sample) error { 106 | if src == nil { 107 | return nil 108 | } 109 | dest.C = src.C 110 | return nil 111 | }, 112 | }, 113 | } 114 | jb._structPropertyMap["A"] = jb.A 115 | jb._jsonPropertyMap["a"] = jb.A 116 | jb._structPropertyMap["B"] = jb.B 117 | jb._jsonPropertyMap["b"] = jb.B 118 | jb._structPropertyMap["C"] = jb.C 119 | jb._jsonPropertyMap["c"] = jb.C 120 | return jb 121 | } 122 | 123 | // Properties returns all properties on SampleJSONBuilder. 124 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 125 | return []*SamplePropertyInfo{ 126 | b.A, 127 | b.B, 128 | b.C, 129 | } 130 | } 131 | 132 | // AddAll adds all property to SampleJSONBuilder. 133 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 134 | b._properties["A"] = b.A 135 | b._properties["B"] = b.B 136 | b._properties["C"] = b.C 137 | return b 138 | } 139 | 140 | // Add specified property to SampleJSONBuilder. 141 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 142 | for _, info := range infos { 143 | b._properties[info.fieldName] = info 144 | } 145 | return b 146 | } 147 | 148 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 149 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 150 | for _, name := range names { 151 | info := b._jsonPropertyMap[name] 152 | if info == nil { 153 | continue 154 | } 155 | b._properties[info.fieldName] = info 156 | } 157 | return b 158 | } 159 | 160 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 161 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 162 | for _, name := range names { 163 | info := b._structPropertyMap[name] 164 | if info == nil { 165 | continue 166 | } 167 | b._properties[info.fieldName] = info 168 | } 169 | return b 170 | } 171 | 172 | // Remove specified property to SampleJSONBuilder. 173 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 174 | for _, info := range infos { 175 | delete(b._properties, info.fieldName) 176 | } 177 | return b 178 | } 179 | 180 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 181 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 182 | 183 | for _, name := range names { 184 | info := b._jsonPropertyMap[name] 185 | if info == nil { 186 | continue 187 | } 188 | delete(b._properties, info.fieldName) 189 | } 190 | return b 191 | } 192 | 193 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 194 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 195 | for _, name := range names { 196 | info := b._structPropertyMap[name] 197 | if info == nil { 198 | continue 199 | } 200 | delete(b._properties, info.fieldName) 201 | } 202 | return b 203 | } 204 | 205 | // Convert specified non-JSON object to JSON object. 206 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 207 | if orig == nil { 208 | return nil, nil 209 | } 210 | ret := &SampleJSON{} 211 | 212 | for _, info := range b._properties { 213 | if err := info.Encoder(orig, ret); err != nil { 214 | return nil, err 215 | } 216 | } 217 | 218 | return ret, nil 219 | } 220 | 221 | // ConvertList specified non-JSON slice to JSONList. 222 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 223 | if orig == nil { 224 | return nil, nil 225 | } 226 | 227 | list := make(SampleJSONList, len(orig)) 228 | for idx, or := range orig { 229 | json, err := b.Convert(or) 230 | if err != nil { 231 | return nil, err 232 | } 233 | list[idx] = json 234 | } 235 | 236 | return list, nil 237 | } 238 | 239 | // Convert specified JSON object to non-JSON object. 240 | func (orig *SampleJSON) Convert() (*Sample, error) { 241 | ret := &Sample{} 242 | 243 | b := NewSampleJSONBuilder().AddAll() 244 | for _, info := range b._properties { 245 | if err := info.Decoder(orig, ret); err != nil { 246 | return nil, err 247 | } 248 | } 249 | 250 | return ret, nil 251 | } 252 | 253 | // Convert specified JSONList to non-JSON slice. 254 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 255 | orig := ([]*SampleJSON)(jsonList) 256 | 257 | list := make([]*Sample, len(orig)) 258 | for idx, or := range orig { 259 | obj, err := or.Convert() 260 | if err != nil { 261 | return nil, err 262 | } 263 | list[idx] = obj 264 | } 265 | 266 | return list, nil 267 | } 268 | 269 | // Marshal non-JSON object to JSON string. 270 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 271 | ret, err := b.Convert(orig) 272 | if err != nil { 273 | return nil, err 274 | } 275 | return json.Marshal(ret) 276 | } 277 | -------------------------------------------------------------------------------- /misc/fixture/t/model.go: -------------------------------------------------------------------------------- 1 | //go:generate jwg -type Sample -output model_json.go -noOmitemptyFieldType=bool,int . 2 | 3 | package t 4 | 5 | type Sample struct { 6 | A string 7 | B string `json:",omitempty"` 8 | C bool 9 | D bool `json:",omitempty"` 10 | E int 11 | F int `json:",omitempty"` 12 | G int64 13 | } 14 | -------------------------------------------------------------------------------- /misc/fixture/t/model_json.go: -------------------------------------------------------------------------------- 1 | // generated by jwg -type Sample -output misc/fixture/t/model_json.go -noOmitemptyFieldType=bool,int misc/fixture/t; DO NOT EDIT 2 | 3 | package t 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // SampleJSON is jsonized struct for Sample. 10 | type SampleJSON struct { 11 | A string `json:"a,omitempty"` 12 | B string `json:"b,omitempty"` 13 | C bool `json:"c"` 14 | D bool `json:"d,omitempty"` 15 | E int `json:"e"` 16 | F int `json:"f,omitempty"` 17 | G int64 `json:"g,omitempty,string"` 18 | } 19 | 20 | // SampleJSONList is synonym about []*SampleJSON. 21 | type SampleJSONList []*SampleJSON 22 | 23 | // SamplePropertyEncoder is property encoder for [1]sJSON. 24 | type SamplePropertyEncoder func(src *Sample, dest *SampleJSON) error 25 | 26 | // SamplePropertyDecoder is property decoder for [1]sJSON. 27 | type SamplePropertyDecoder func(src *SampleJSON, dest *Sample) error 28 | 29 | // SamplePropertyInfo stores property information. 30 | type SamplePropertyInfo struct { 31 | fieldName string 32 | jsonName string 33 | Encoder SamplePropertyEncoder 34 | Decoder SamplePropertyDecoder 35 | } 36 | 37 | // FieldName returns struct field name of property. 38 | func (info *SamplePropertyInfo) FieldName() string { 39 | return info.fieldName 40 | } 41 | 42 | // JSONName returns json field name of property. 43 | func (info *SamplePropertyInfo) JSONName() string { 44 | return info.jsonName 45 | } 46 | 47 | // SampleJSONBuilder convert between Sample to SampleJSON mutually. 48 | type SampleJSONBuilder struct { 49 | _properties map[string]*SamplePropertyInfo 50 | _jsonPropertyMap map[string]*SamplePropertyInfo 51 | _structPropertyMap map[string]*SamplePropertyInfo 52 | A *SamplePropertyInfo 53 | B *SamplePropertyInfo 54 | C *SamplePropertyInfo 55 | D *SamplePropertyInfo 56 | E *SamplePropertyInfo 57 | F *SamplePropertyInfo 58 | G *SamplePropertyInfo 59 | } 60 | 61 | // NewSampleJSONBuilder make new SampleJSONBuilder. 62 | func NewSampleJSONBuilder() *SampleJSONBuilder { 63 | jb := &SampleJSONBuilder{ 64 | _properties: map[string]*SamplePropertyInfo{}, 65 | _jsonPropertyMap: map[string]*SamplePropertyInfo{}, 66 | _structPropertyMap: map[string]*SamplePropertyInfo{}, 67 | A: &SamplePropertyInfo{ 68 | fieldName: "A", 69 | jsonName: "a", 70 | Encoder: func(src *Sample, dest *SampleJSON) error { 71 | if src == nil { 72 | return nil 73 | } 74 | dest.A = src.A 75 | return nil 76 | }, 77 | Decoder: func(src *SampleJSON, dest *Sample) error { 78 | if src == nil { 79 | return nil 80 | } 81 | dest.A = src.A 82 | return nil 83 | }, 84 | }, 85 | B: &SamplePropertyInfo{ 86 | fieldName: "B", 87 | jsonName: "b", 88 | Encoder: func(src *Sample, dest *SampleJSON) error { 89 | if src == nil { 90 | return nil 91 | } 92 | dest.B = src.B 93 | return nil 94 | }, 95 | Decoder: func(src *SampleJSON, dest *Sample) error { 96 | if src == nil { 97 | return nil 98 | } 99 | dest.B = src.B 100 | return nil 101 | }, 102 | }, 103 | C: &SamplePropertyInfo{ 104 | fieldName: "C", 105 | jsonName: "c", 106 | Encoder: func(src *Sample, dest *SampleJSON) error { 107 | if src == nil { 108 | return nil 109 | } 110 | dest.C = src.C 111 | return nil 112 | }, 113 | Decoder: func(src *SampleJSON, dest *Sample) error { 114 | if src == nil { 115 | return nil 116 | } 117 | dest.C = src.C 118 | return nil 119 | }, 120 | }, 121 | D: &SamplePropertyInfo{ 122 | fieldName: "D", 123 | jsonName: "d", 124 | Encoder: func(src *Sample, dest *SampleJSON) error { 125 | if src == nil { 126 | return nil 127 | } 128 | dest.D = src.D 129 | return nil 130 | }, 131 | Decoder: func(src *SampleJSON, dest *Sample) error { 132 | if src == nil { 133 | return nil 134 | } 135 | dest.D = src.D 136 | return nil 137 | }, 138 | }, 139 | E: &SamplePropertyInfo{ 140 | fieldName: "E", 141 | jsonName: "e", 142 | Encoder: func(src *Sample, dest *SampleJSON) error { 143 | if src == nil { 144 | return nil 145 | } 146 | dest.E = src.E 147 | return nil 148 | }, 149 | Decoder: func(src *SampleJSON, dest *Sample) error { 150 | if src == nil { 151 | return nil 152 | } 153 | dest.E = src.E 154 | return nil 155 | }, 156 | }, 157 | F: &SamplePropertyInfo{ 158 | fieldName: "F", 159 | jsonName: "f", 160 | Encoder: func(src *Sample, dest *SampleJSON) error { 161 | if src == nil { 162 | return nil 163 | } 164 | dest.F = src.F 165 | return nil 166 | }, 167 | Decoder: func(src *SampleJSON, dest *Sample) error { 168 | if src == nil { 169 | return nil 170 | } 171 | dest.F = src.F 172 | return nil 173 | }, 174 | }, 175 | G: &SamplePropertyInfo{ 176 | fieldName: "G", 177 | jsonName: "g", 178 | Encoder: func(src *Sample, dest *SampleJSON) error { 179 | if src == nil { 180 | return nil 181 | } 182 | dest.G = src.G 183 | return nil 184 | }, 185 | Decoder: func(src *SampleJSON, dest *Sample) error { 186 | if src == nil { 187 | return nil 188 | } 189 | dest.G = src.G 190 | return nil 191 | }, 192 | }, 193 | } 194 | jb._structPropertyMap["A"] = jb.A 195 | jb._jsonPropertyMap["a"] = jb.A 196 | jb._structPropertyMap["B"] = jb.B 197 | jb._jsonPropertyMap["b"] = jb.B 198 | jb._structPropertyMap["C"] = jb.C 199 | jb._jsonPropertyMap["c"] = jb.C 200 | jb._structPropertyMap["D"] = jb.D 201 | jb._jsonPropertyMap["d"] = jb.D 202 | jb._structPropertyMap["E"] = jb.E 203 | jb._jsonPropertyMap["e"] = jb.E 204 | jb._structPropertyMap["F"] = jb.F 205 | jb._jsonPropertyMap["f"] = jb.F 206 | jb._structPropertyMap["G"] = jb.G 207 | jb._jsonPropertyMap["g"] = jb.G 208 | return jb 209 | } 210 | 211 | // Properties returns all properties on SampleJSONBuilder. 212 | func (b *SampleJSONBuilder) Properties() []*SamplePropertyInfo { 213 | return []*SamplePropertyInfo{ 214 | b.A, 215 | b.B, 216 | b.C, 217 | b.D, 218 | b.E, 219 | b.F, 220 | b.G, 221 | } 222 | } 223 | 224 | // AddAll adds all property to SampleJSONBuilder. 225 | func (b *SampleJSONBuilder) AddAll() *SampleJSONBuilder { 226 | b._properties["A"] = b.A 227 | b._properties["B"] = b.B 228 | b._properties["C"] = b.C 229 | b._properties["D"] = b.D 230 | b._properties["E"] = b.E 231 | b._properties["F"] = b.F 232 | b._properties["G"] = b.G 233 | return b 234 | } 235 | 236 | // Add specified property to SampleJSONBuilder. 237 | func (b *SampleJSONBuilder) Add(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 238 | for _, info := range infos { 239 | b._properties[info.fieldName] = info 240 | } 241 | return b 242 | } 243 | 244 | // AddByJSONNames add properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 245 | func (b *SampleJSONBuilder) AddByJSONNames(names ...string) *SampleJSONBuilder { 246 | for _, name := range names { 247 | info := b._jsonPropertyMap[name] 248 | if info == nil { 249 | continue 250 | } 251 | b._properties[info.fieldName] = info 252 | } 253 | return b 254 | } 255 | 256 | // AddByNames add properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 257 | func (b *SampleJSONBuilder) AddByNames(names ...string) *SampleJSONBuilder { 258 | for _, name := range names { 259 | info := b._structPropertyMap[name] 260 | if info == nil { 261 | continue 262 | } 263 | b._properties[info.fieldName] = info 264 | } 265 | return b 266 | } 267 | 268 | // Remove specified property to SampleJSONBuilder. 269 | func (b *SampleJSONBuilder) Remove(infos ...*SamplePropertyInfo) *SampleJSONBuilder { 270 | for _, info := range infos { 271 | delete(b._properties, info.fieldName) 272 | } 273 | return b 274 | } 275 | 276 | // RemoveByJSONNames remove properties to SampleJSONBuilder by JSON property name. if name is not in the builder, it will ignore. 277 | func (b *SampleJSONBuilder) RemoveByJSONNames(names ...string) *SampleJSONBuilder { 278 | 279 | for _, name := range names { 280 | info := b._jsonPropertyMap[name] 281 | if info == nil { 282 | continue 283 | } 284 | delete(b._properties, info.fieldName) 285 | } 286 | return b 287 | } 288 | 289 | // RemoveByNames remove properties to SampleJSONBuilder by struct property name. if name is not in the builder, it will ignore. 290 | func (b *SampleJSONBuilder) RemoveByNames(names ...string) *SampleJSONBuilder { 291 | for _, name := range names { 292 | info := b._structPropertyMap[name] 293 | if info == nil { 294 | continue 295 | } 296 | delete(b._properties, info.fieldName) 297 | } 298 | return b 299 | } 300 | 301 | // Convert specified non-JSON object to JSON object. 302 | func (b *SampleJSONBuilder) Convert(orig *Sample) (*SampleJSON, error) { 303 | if orig == nil { 304 | return nil, nil 305 | } 306 | ret := &SampleJSON{} 307 | 308 | for _, info := range b._properties { 309 | if err := info.Encoder(orig, ret); err != nil { 310 | return nil, err 311 | } 312 | } 313 | 314 | return ret, nil 315 | } 316 | 317 | // ConvertList specified non-JSON slice to JSONList. 318 | func (b *SampleJSONBuilder) ConvertList(orig []*Sample) (SampleJSONList, error) { 319 | if orig == nil { 320 | return nil, nil 321 | } 322 | 323 | list := make(SampleJSONList, len(orig)) 324 | for idx, or := range orig { 325 | json, err := b.Convert(or) 326 | if err != nil { 327 | return nil, err 328 | } 329 | list[idx] = json 330 | } 331 | 332 | return list, nil 333 | } 334 | 335 | // Convert specified JSON object to non-JSON object. 336 | func (orig *SampleJSON) Convert() (*Sample, error) { 337 | ret := &Sample{} 338 | 339 | b := NewSampleJSONBuilder().AddAll() 340 | for _, info := range b._properties { 341 | if err := info.Decoder(orig, ret); err != nil { 342 | return nil, err 343 | } 344 | } 345 | 346 | return ret, nil 347 | } 348 | 349 | // Convert specified JSONList to non-JSON slice. 350 | func (jsonList SampleJSONList) Convert() ([]*Sample, error) { 351 | orig := ([]*SampleJSON)(jsonList) 352 | 353 | list := make([]*Sample, len(orig)) 354 | for idx, or := range orig { 355 | obj, err := or.Convert() 356 | if err != nil { 357 | return nil, err 358 | } 359 | list[idx] = obj 360 | } 361 | 362 | return list, nil 363 | } 364 | 365 | // Marshal non-JSON object to JSON string. 366 | func (b *SampleJSONBuilder) Marshal(orig *Sample) ([]byte, error) { 367 | ret, err := b.Convert(orig) 368 | if err != nil { 369 | return nil, err 370 | } 371 | return json.Marshal(ret) 372 | } 373 | -------------------------------------------------------------------------------- /misc/other/v1/model.go: -------------------------------------------------------------------------------- 1 | package other 2 | 3 | type Test struct { 4 | Foo int 5 | } 6 | -------------------------------------------------------------------------------- /misc/other/v2/model.go: -------------------------------------------------------------------------------- 1 | package other 2 | 3 | type Test struct { 4 | Foo string 5 | } 6 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | dep ensure 2 | 3 | # build tools 4 | rm -rf build-cmd/ 5 | mkdir build-cmd 6 | go build -o build-cmd/goimports ./vendor/golang.org/x/tools/cmd/goimports 7 | go build -o build-cmd/golint ./vendor/github.com/golang/lint/golint 8 | 9 | go run cmd/jwg/main.go -type Sample -output misc/fixture/a/model_json.go misc/fixture/a 10 | go run cmd/jwg/main.go -type Sample -output misc/fixture/b/model_json.go misc/fixture/b 11 | go run cmd/jwg/main.go -type Sample -output misc/fixture/c/model_json.go misc/fixture/c 12 | go run cmd/jwg/main.go -output misc/fixture/d/model_json.go misc/fixture/d 13 | go run cmd/jwg/main.go -type Sample -output misc/fixture/e/model_json.go misc/fixture/e 14 | go run cmd/jwg/main.go -type SampleF -output misc/fixture/f/model_json.go misc/fixture/f 15 | go run cmd/jwg/main.go -type Sample,Inner -output misc/fixture/g/model_json.go misc/fixture/g 16 | go run cmd/jwg/main.go -type Sample -output misc/fixture/h/model_json.go misc/fixture/h 17 | go run cmd/jwg/main.go -output misc/fixture/i/model_json.go misc/fixture/i 18 | go run cmd/jwg/main.go -output misc/fixture/j/model_json.go misc/fixture/j 19 | go run cmd/jwg/main.go -output misc/fixture/k/model_json.go misc/fixture/k 20 | go run cmd/jwg/main.go -type Sample -output misc/fixture/l/model_json.go -transcripttag swagger,includes misc/fixture/l 21 | go run cmd/jwg/main.go -type Sample -output misc/fixture/m/model_json.go misc/fixture/m 22 | go run cmd/jwg/main.go -type Sample -output misc/fixture/n/model_json.go -noOmitempty misc/fixture/n 23 | go run cmd/jwg/main.go -type Sample -output misc/fixture/t/model_json.go -noOmitemptyFieldType=bool,int misc/fixture/t 24 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eux 2 | 3 | targets=`find . -type f \( -name '*.go' -and -not -iwholename '*vendor*' -and -not -iwholename '*misc*' \)` 4 | packages=`go list ./... | grep -v misc` 5 | 6 | # Apply tools 7 | export PATH=$(pwd)/build-cmd:$PATH 8 | which goimports golint 9 | goimports -w $targets 10 | go tool vet $targets 11 | golint $packages 12 | 13 | go test $packages $@ 14 | -------------------------------------------------------------------------------- /usage_test.go: -------------------------------------------------------------------------------- 1 | package jwg 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/favclip/jwg/misc/fixture/a" 8 | "github.com/favclip/jwg/misc/fixture/b" 9 | "github.com/favclip/jwg/misc/fixture/e" 10 | "github.com/favclip/jwg/misc/fixture/f" 11 | i "github.com/favclip/jwg/misc/fixture/i" 12 | ) 13 | 14 | func TestBasicUsage1(t *testing.T) { 15 | src := &a.Sample{"Foo!"} 16 | 17 | builder := a.NewSampleJSONBuilder() 18 | builder.AddAll() 19 | jsonStruct, err := builder.Convert(src) 20 | if err != nil { 21 | t.Log(err) 22 | t.Fail() 23 | } 24 | 25 | json, err := json.Marshal(jsonStruct) 26 | 27 | if err != nil { 28 | t.Log(err) 29 | t.Fail() 30 | } 31 | 32 | if string(json) != `{"foo":"Foo!"}` { 33 | t.Log("json is not expected, actual", string(json)) 34 | t.Fail() 35 | } 36 | } 37 | 38 | func TestBasicUsage2(t *testing.T) { 39 | src := &a.Sample{"Foo!"} 40 | 41 | builder := a.NewSampleJSONBuilder() 42 | builder.AddAll() 43 | json, err := builder.Marshal(src) 44 | 45 | if err != nil { 46 | t.Log(err) 47 | t.Fail() 48 | } 49 | 50 | if string(json) != `{"foo":"Foo!"}` { 51 | t.Log("json is not expected, actual", string(json)) 52 | t.Fail() 53 | } 54 | } 55 | 56 | func TestBasicUsage3(t *testing.T) { 57 | src := &a.Sample{"Foo!"} 58 | 59 | builder := a.NewSampleJSONBuilder() 60 | builder.AddByJSONNames("foo") 61 | json, err := builder.Marshal(src) 62 | 63 | if err != nil { 64 | t.Log(err) 65 | t.Fail() 66 | } 67 | 68 | if string(json) != `{"foo":"Foo!"}` { 69 | t.Log("json is not expected, actual", string(json)) 70 | t.Fail() 71 | } 72 | } 73 | 74 | func TestBasicUsage4(t *testing.T) { 75 | src := &a.Sample{"Foo!"} 76 | 77 | builder := a.NewSampleJSONBuilder() 78 | builder.AddByNames("Foo") 79 | json, err := builder.Marshal(src) 80 | 81 | if err != nil { 82 | t.Log(err) 83 | t.Fail() 84 | } 85 | 86 | if string(json) != `{"foo":"Foo!"}` { 87 | t.Log("json is not expected, actual", string(json)) 88 | t.Fail() 89 | } 90 | } 91 | 92 | func TestWithRemove(t *testing.T) { 93 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 94 | 95 | builder := b.NewSampleJSONBuilder() 96 | builder.AddAll() 97 | builder.Remove(builder.A, builder.D) 98 | json, err := builder.Marshal(src) 99 | 100 | if err != nil { 101 | t.Log(err) 102 | t.Fail() 103 | } 104 | 105 | // A, D was removed. C was omitted. E was ignored. 106 | if string(json) != `{"b":"B"}` { 107 | t.Log("json is not expected, actual", string(json)) 108 | t.Fail() 109 | } 110 | } 111 | 112 | func TestWithRemoveByNames(t *testing.T) { 113 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 114 | 115 | builder := b.NewSampleJSONBuilder() 116 | builder.AddAll() 117 | builder.RemoveByNames() // ignore empty 118 | builder.RemoveByNames("A", "D", "hoge") // ignore non-exist property 119 | json, err := builder.Marshal(src) 120 | 121 | if err != nil { 122 | t.Log(err) 123 | t.Fail() 124 | } 125 | 126 | // A, D was removed. C was omitted. E was ignored. 127 | if string(json) != `{"b":"B"}` { 128 | t.Log("json is not expected, actual", string(json)) 129 | t.Fail() 130 | } 131 | } 132 | 133 | func TestWithRemoveByJSONNames(t *testing.T) { 134 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 135 | 136 | builder := b.NewSampleJSONBuilder() 137 | builder.AddAll() 138 | builder.RemoveByJSONNames() // ignore empty 139 | builder.RemoveByJSONNames("foo!", "d", "fuga") // ignore non-exist property 140 | json, err := builder.Marshal(src) 141 | 142 | if err != nil { 143 | t.Log(err) 144 | t.Fail() 145 | } 146 | 147 | // A, D was removed. C was omitted. E was ignored. 148 | if string(json) != `{"b":"B"}` { 149 | t.Log("json is not expected, actual", string(json)) 150 | t.Fail() 151 | } 152 | } 153 | 154 | func TestWithAdd(t *testing.T) { 155 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 156 | 157 | builder := b.NewSampleJSONBuilder() 158 | builder.Add(builder.D, builder.A) 159 | json, err := builder.Marshal(src) 160 | 161 | if err != nil { 162 | t.Log(err) 163 | t.Fail() 164 | } 165 | 166 | if string(json) != `{"foo!":"A","d":"1"}` { 167 | t.Log("json is not expected, actual", string(json)) 168 | t.Fail() 169 | } 170 | } 171 | 172 | func TestWithAddByJSONNames(t *testing.T) { 173 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 174 | 175 | builder := b.NewSampleJSONBuilder() 176 | builder.AddByJSONNames() // ignore empty 177 | builder.AddByJSONNames("b", "d", "hoge") // ignore non-exist property 178 | json, err := builder.Marshal(src) 179 | 180 | if err != nil { 181 | t.Log(err) 182 | t.Fail() 183 | } 184 | 185 | if string(json) != `{"b":"B","d":"1"}` { 186 | t.Log("json is not expected, actual", string(json)) 187 | t.Fail() 188 | } 189 | } 190 | 191 | func TestWithAddByNames(t *testing.T) { 192 | src := &b.Sample{"A", "B", 0, 1, "E", 0, nil} 193 | 194 | builder := b.NewSampleJSONBuilder() 195 | builder.AddByNames() // ignore empty 196 | builder.AddByNames("B", "D", "hoge") // ignore non-exist property 197 | json, err := builder.Marshal(src) 198 | 199 | if err != nil { 200 | t.Log(err) 201 | t.Fail() 202 | } 203 | 204 | if string(json) != `{"b":"B","d":"1"}` { 205 | t.Log("json is not expected, actual", string(json)) 206 | t.Fail() 207 | } 208 | } 209 | 210 | func TestReplacePropertyBuilder1(t *testing.T) { 211 | src := &a.Sample{"Foo"} 212 | 213 | builder := a.NewSampleJSONBuilder() 214 | builder.Foo.Encoder = func(src *a.Sample, dest *a.SampleJSON) error { 215 | dest.Foo = src.Foo + "!!!" 216 | return nil 217 | } 218 | builder.AddAll() 219 | json, err := builder.Marshal(src) 220 | 221 | if err != nil { 222 | t.Log(err) 223 | t.Fail() 224 | } 225 | 226 | if string(json) != `{"foo":"Foo!!!"}` { 227 | t.Log("json is not expected, actual", string(json)) 228 | t.Fail() 229 | } 230 | } 231 | 232 | func TestReplacePropertyBuilder2(t *testing.T) { 233 | builder := i.NewPeopleJSONBuilder() 234 | builder.AddAll() 235 | builder.Remove(builder.ShowPrivateInfo) 236 | builder.List.Encoder = func(src *i.People, dest *i.PeopleJSON) error { 237 | if src == nil { 238 | return nil 239 | } 240 | b := i.NewPersonJSONBuilder().AddAll() 241 | if !src.ShowPrivateInfo { 242 | b.Remove(b.Password) 243 | } 244 | list, err := b.ConvertList(src.List) 245 | if err != nil { 246 | return err 247 | } 248 | dest.List = ([]*i.PersonJSON)(list) 249 | return nil 250 | } 251 | 252 | people := &i.People{ShowPrivateInfo: false, List: []*i.Person{&i.Person{ 253 | Name: "vvakame", 254 | Age: 30, 255 | Password: "pw", 256 | }}} 257 | json, err := builder.Convert(people) 258 | if err != nil { 259 | t.Log(err) 260 | t.Fail() 261 | } 262 | 263 | if len(json.List) != 1 { 264 | t.Log("json.List is not expected, actual", len(json.List)) 265 | t.Fail() 266 | } 267 | if json.List[0].Password != "" { 268 | t.Log("password is not expected, actual", json.List[0].Password) 269 | t.Fail() 270 | } 271 | } 272 | 273 | func TestWithPointerField(t *testing.T) { 274 | str := "Hi!" 275 | src := &e.Sample{ 276 | &str, 277 | &e.Foo{}, 278 | } 279 | 280 | builder := e.NewSampleJSONBuilder() 281 | builder.AddAll() 282 | json, err := builder.Marshal(src) 283 | 284 | if err != nil { 285 | t.Log(err) 286 | t.Fail() 287 | } 288 | 289 | if string(json) != `{"str":"Hi!","foo":{}}` { 290 | t.Log("json is not expected, actual", string(json)) 291 | t.Fail() 292 | } 293 | } 294 | 295 | func TestWithImportStatement(t *testing.T) { 296 | src := &f.SampleF{nil, nil} 297 | 298 | builder := f.NewSampleFJSONBuilder() 299 | builder.AddAll() 300 | json, err := builder.Marshal(src) 301 | 302 | if err != nil { 303 | t.Log(err) 304 | t.Fail() 305 | } 306 | 307 | if string(json) != `{}` { 308 | t.Log("json is not expected, actual", string(json)) 309 | t.Fail() 310 | } 311 | } 312 | 313 | func TestConvertJsonStructToVanillaStruct(t *testing.T) { 314 | json := &a.SampleJSON{"foo!"} 315 | src, err := json.Convert() 316 | if err != nil { 317 | t.Log(err) 318 | t.Fail() 319 | } 320 | 321 | if src.Foo != "foo!" { 322 | t.Log("src.Foo is not expected, actual", src.Foo) 323 | t.Fail() 324 | } 325 | } 326 | --------------------------------------------------------------------------------