· 7 years ago · Dec 03, 2018, 08:22 PM
1{ "bit_size": 8, "secret_key": false }
2
3{ "num_bits": 8 }
4
5type DB struct {
6 NumBits int `json:"bit_size"`
7 Secret bool `json:"secret_key"`
8}
9type User struct {
10 NumBits int `json:"num_bits"`
11}
12
13package main
14
15import (
16 "encoding/json"
17 "fmt"
18 "reflect"
19)
20
21type M map[string]interface{} // just an alias
22
23var Record = []byte(`{ "bit_size": 8, "secret_key": false }`)
24
25type DB struct {
26 NumBits int `json:"bit_size"`
27 Secret bool `json:"secret_key"`
28}
29
30type User struct {
31 NumBits int `json:"num_bits"`
32}
33
34func main() {
35 d := new(DB)
36 e := json.Unmarshal(Record, d)
37 if e != nil {
38 panic(e)
39 }
40 m := mapFields(d)
41 fmt.Println("Mapped fields: ", m)
42 u := new(User)
43 o := applyMap(u, m)
44 fmt.Println("Applied map: ", o)
45 j, e := json.Marshal(o)
46 if e != nil {
47 panic(e)
48 }
49 fmt.Println("Output JSON: ", string(j))
50}
51
52func applyMap(u *User, m M) M {
53 t := reflect.TypeOf(u).Elem()
54 o := make(M)
55 for i := 0; i < t.NumField(); i++ {
56 f := t.FieldByIndex([]int{i})
57 // skip unexported fields
58 if f.PkgPath != "" {
59 continue
60 }
61 if x, ok := m[f.Name]; ok {
62 k := f.Tag.Get("json")
63 o[k] = x
64 }
65 }
66 return o
67}
68
69func mapFields(x *DB) M {
70 o := make(M)
71 v := reflect.ValueOf(x).Elem()
72 t := v.Type()
73 for i := 0; i < v.NumField(); i++ {
74 f := t.FieldByIndex([]int{i})
75 // skip unexported fields
76 if f.PkgPath != "" {
77 continue
78 }
79 o[f.Name] = v.FieldByIndex([]int{i}).Interface()
80 }
81 return o
82}
83
84package main
85
86import (
87 "fmt"
88)
89
90type DB struct {
91 User
92 Secret bool `json:"secret_key"`
93}
94
95type User struct {
96 NumBits int `json:"num_bits"`
97}
98
99func main() {
100 db := DB{User{10}, true}
101 fmt.Printf("Hello, DB: %+vn", db)
102 fmt.Printf("Hello, DB.NumBits: %+vn", db.NumBits)
103 fmt.Printf("Hello, User: %+vn", db.User)
104}
105
106buf := bytes.Buffer{}
107err := gob.NewEncoder(&buf).Encode(&DbVar)
108if err != nil {
109 return err
110}
111u := User{}
112err = gob.NewDecoder(&buf).Decode(&u)
113if err != nil {
114 return err
115}
116
117package main
118
119import (
120 "fmt"
121 "log"
122
123 "hacked/json"
124)
125
126var dbj = `{ "bit_size": 8, "secret_key": false }`
127
128type User struct {
129 NumBits int `json:"bit_size" api:"num_bits"`
130}
131
132func main() {
133 fmt.Println(dbj)
134 // unmarshal from full db record to User struct
135 var u User
136 if err := json.Unmarshal([]byte(dbj), &u); err != nil {
137 log.Fatal(err)
138 }
139 // remarshal User struct using api field names
140 api, err := json.MarshalTag(u, "api")
141 if err != nil {
142 log.Fatal(err)
143 }
144 fmt.Println(string(api))
145}
146
147106c106,112
148< e := &encodeState{}
149---
150> return MarshalTag(v, "json")
151> }
152>
153> // MarshalTag is like Marshal but marshalls fields with
154> // the specified tag key instead of the default "json".
155> func MarshalTag(v interface{}, tag string) ([]byte, error) {
156> e := &encodeState{tagKey: tag}
157201a208
158> tagKey string
159328c335
160< for _, ef := range encodeFields(v.Type()) {
161---
162> for _, ef := range encodeFields(v.Type(), e.tagKey) {
163509c516
164< func encodeFields(t reflect.Type) []encodeField {
165---
166> func encodeFields(t reflect.Type, tagKey string) []encodeField {
167540c547
168< tv := f.Tag.Get("json")
169---
170> tv := f.Tag.Get(tagKey)
171
172package main
173
174import (
175 "encoding/json"
176 "fmt"
177 "log"
178)
179
180// example full database record
181var dbj = `{ "bit_size": 8, "secret_key": false }`
182
183// User type has only the fields going to the API
184type User struct {
185 // tag still specifies internal name, not API name
186 NumBits int `json:"bit_size"`
187}
188
189// mapping from internal field names to API field names.
190// (you could have more than one mapping, or even construct this
191// at run time)
192var ApiField = map[string]string{
193 // internal: API
194 "bit_size": "num_bits",
195 // ...
196}
197
198func main() {
199 fmt.Println(dbj)
200 // select user fields from full db record by unmarshalling
201 var u User
202 if err := json.Unmarshal([]byte(dbj), &u); err != nil {
203 log.Fatal(err)
204 }
205 // remarshal from User struct back to json
206 exportable, err := json.Marshal(u)
207 if err != nil {
208 log.Fatal(err)
209 }
210 // unmarshal into a map this time, to shrug field tags.
211 type jmap map[string]interface{}
212 mInternal := jmap{}
213 if err := json.Unmarshal(exportable, &mInternal); err != nil {
214 log.Fatal(err)
215 }
216 // translate field names
217 mExportable := jmap{}
218 for internalField, v := range mInternal {
219 mExportable[ApiField[internalField]] = v
220 }
221 // marshal final result with API field names
222 if exportable, err = json.Marshal(mExportable); err != nil {
223 log.Fatal(err)
224 }
225 fmt.Println(string(exportable))
226}
227
228package main
229
230import (
231 "encoding/json"
232 "fmt"
233 "log"
234)
235
236var dbj = `{ "bit_size": 8, "secret_key": false }`
237
238// translation from internal field name to api field name
239type apiTrans struct {
240 db, api string
241}
242
243var User = []apiTrans{
244 {db: "bit_size", api: "num_bits"},
245}
246
247func main() {
248 fmt.Println(dbj)
249 type jmap map[string]interface{}
250 // unmarshal full db record
251 mdb := jmap{}
252 if err := json.Unmarshal([]byte(dbj), &mdb); err != nil {
253 log.Fatal(err)
254 }
255 // build result
256 mres := jmap{}
257 for _, t := range User {
258 if v, ok := mdb[t.db]; ok {
259 mres[t.api] = v
260 }
261 }
262 // marshal result
263 exportable, err := json.Marshal(mres)
264 if err != nil {
265 log.Fatal(err)
266 }
267 fmt.Println(string(exportable))
268}