funcr: Support embedded types like std json does
Also add tests.
Tim Hockin
2 years ago
259 | 259 |
}
|
260 | 260 |
|
261 | 261 |
const (
|
262 | |
flagRawString = 0x1
|
|
262 |
flagRawString = 0x1 // do not print quotes on strings
|
|
263 |
flagRawStruct = 0x2 // do not print braces on structs
|
263 | 264 |
)
|
264 | 265 |
|
265 | 266 |
// TODO: This is not fast. Most of the overhead goes here.
|
|
349 | 350 |
case reflect.Complex128:
|
350 | 351 |
return `"` + strconv.FormatComplex(v.Complex(), 'f', -1, 128) + `"`
|
351 | 352 |
case reflect.Struct:
|
352 | |
buf.WriteByte('{')
|
|
353 |
if flags&flagRawStruct == 0 {
|
|
354 |
buf.WriteByte('{')
|
|
355 |
}
|
353 | 356 |
for i := 0; i < t.NumField(); i++ {
|
354 | 357 |
fld := t.Field(i)
|
355 | 358 |
if fld.PkgPath != "" {
|
|
360 | 363 |
// reflect isn't clear exactly what this means, but we can't use it.
|
361 | 364 |
continue
|
362 | 365 |
}
|
363 | |
name := fld.Name
|
|
366 |
name := ""
|
364 | 367 |
omitempty := false
|
365 | 368 |
if tag, found := fld.Tag.Lookup("json"); found {
|
366 | 369 |
if tag == "-" {
|
|
384 | 387 |
if i > 0 {
|
385 | 388 |
buf.WriteByte(',')
|
386 | 389 |
}
|
|
390 |
if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" {
|
|
391 |
buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct))
|
|
392 |
continue
|
|
393 |
}
|
|
394 |
if name == "" {
|
|
395 |
name = fld.Name
|
|
396 |
}
|
387 | 397 |
buf.WriteByte('"')
|
388 | 398 |
buf.WriteString(name)
|
389 | 399 |
buf.WriteByte('"')
|
390 | 400 |
buf.WriteByte(':')
|
391 | 401 |
buf.WriteString(f.pretty(v.Field(i).Interface()))
|
392 | 402 |
}
|
393 | |
buf.WriteByte('}')
|
|
403 |
if flags&flagRawStruct == 0 {
|
|
404 |
buf.WriteByte('}')
|
|
405 |
}
|
394 | 406 |
return buf.String()
|
395 | 407 |
case reflect.Slice, reflect.Array:
|
396 | 408 |
buf.WriteByte('[')
|
148 | 148 |
Map4 map[string]string `json:"map4,omitempty"` // renamed, ignore if empty
|
149 | 149 |
Map5 map[string]string `json:","` // no-op
|
150 | 150 |
Map6 map[string]string `json:",omitempty"` // ignore if empty
|
|
151 |
}
|
|
152 |
|
|
153 |
type Tinnerstruct struct {
|
|
154 |
Inner string
|
|
155 |
}
|
|
156 |
type Tinnerint int
|
|
157 |
type Tinnermap map[string]string
|
|
158 |
type Tinnerslice []string
|
|
159 |
|
|
160 |
type Tembedstruct struct {
|
|
161 |
Tinnerstruct
|
|
162 |
Outer string
|
|
163 |
}
|
|
164 |
|
|
165 |
type Tembednonstruct struct {
|
|
166 |
Tinnerint
|
|
167 |
Tinnermap
|
|
168 |
Tinnerslice
|
|
169 |
}
|
|
170 |
|
|
171 |
type Tinner1 Tinnerstruct
|
|
172 |
type Tinner2 Tinnerstruct
|
|
173 |
type Tinner3 Tinnerstruct
|
|
174 |
type Tinner4 Tinnerstruct
|
|
175 |
type Tinner5 Tinnerstruct
|
|
176 |
type Tinner6 Tinnerstruct
|
|
177 |
|
|
178 |
type Tembedjsontags struct {
|
|
179 |
Outer string
|
|
180 |
Tinner1 `json:"inner1"`
|
|
181 |
Tinner2 `json:"-"`
|
|
182 |
Tinner3 `json:"-,"`
|
|
183 |
Tinner4 `json:"inner4,omitempty"`
|
|
184 |
Tinner5 `json:","`
|
|
185 |
Tinner6 `json:"inner6,omitempty"`
|
151 | 186 |
}
|
152 | 187 |
|
153 | 188 |
func TestPretty(t *testing.T) {
|
|
391 | 426 |
val: TjsontagsMap{},
|
392 | 427 |
exp: `{"map1":{},"-":{},"Map5":{}}`,
|
393 | 428 |
},
|
|
429 |
{val: Tembedstruct{}},
|
|
430 |
{
|
|
431 |
val: Tembednonstruct{},
|
|
432 |
exp: `{"Tinnerint":0,"Tinnermap":{},"Tinnerslice":[]}`,
|
|
433 |
},
|
|
434 |
{val: Tembedjsontags{}},
|
394 | 435 |
}
|
395 | 436 |
|
396 | 437 |
f := NewFormatter(Options{})
|