Codebase list golang-github-go-logr-logr / c9b68e6
func: Implement TextMarshaler for map keys Tim Hockin 2 years ago
2 changed file(s) with 44 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
3535
3636 import (
3737 "bytes"
38 "encoding"
3839 "fmt"
3940 "path/filepath"
4041 "reflect"
491492 if i > 0 {
492493 buf.WriteByte(',')
493494 }
494 // prettyWithFlags will produce already-escaped values
495 keystr := f.prettyWithFlags(it.Key().Interface(), 0)
496 if t.Key().Kind() != reflect.String {
497 // JSON only does string keys. Unlike Go's standard JSON, we'll
498 // convert just about anything to a string.
495 // If a map key supports TextMarshaler, use it.
496 keystr := ""
497 if m, ok := it.Key().Interface().(encoding.TextMarshaler); ok {
498 txt, err := m.MarshalText()
499 if err != nil {
500 keystr = fmt.Sprintf("<error-MarshalText: %s>", err.Error())
501 } else {
502 keystr = string(txt)
503 }
499504 keystr = prettyString(keystr)
505 } else {
506 // prettyWithFlags will produce already-escaped values
507 keystr = f.prettyWithFlags(it.Key().Interface(), 0)
508 if t.Key().Kind() != reflect.String {
509 // JSON only does string keys. Unlike Go's standard JSON, we'll
510 // convert just about anything to a string.
511 keystr = prettyString(keystr)
512 }
500513 }
501514 buf.WriteString(keystr)
502515 buf.WriteByte(':')
3434 }
3535 func ptrstr(s string) *string {
3636 return &s
37 }
38
39 // point implements encoding.TextMarshaler and can be used as a map key.
40 type point struct{ x, y int }
41
42 func (p point) MarshalText() ([]byte, error) {
43 return []byte(fmt.Sprintf("(%d, %d)", p.x, p.y)), nil
44 }
45
46 // pointErr implements encoding.TextMarshaler but returns an error.
47 type pointErr struct{ x, y int }
48
49 func (p pointErr) MarshalText() ([]byte, error) {
50 return nil, fmt.Errorf("uh oh: %d, %d", p.x, p.y)
3751 }
3852
3953 // Logging this should result in the MarshalLog() value.
288302 exp: `{"9.5":3}`,
289303 },
290304 {
305 val: map[point]int{
306 {x: 1, y: 2}: 3,
307 },
308 },
309 {
310 val: map[pointErr]int{
311 {x: 1, y: 2}: 3,
312 },
313 exp: `{"<error-MarshalText: uh oh: 1, 2>":3}`,
314 },
315 {
291316 val: struct {
292317 X int `json:"x"`
293318 Y int `json:"y"`
495520 } else {
496521 jb, err := json.Marshal(tc.val)
497522 if err != nil {
498 t.Fatalf("[%d]: unexpected error: %v", i, err)
523 t.Fatalf("[%d]: unexpected error: %v\ngot: %q", i, err, ours)
499524 }
500525 want = string(jb)
501526 }