github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/perf/json/human_friendly.go (about) 1 package json 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 8 jsoniter "github.com/json-iterator/go" 9 10 "github.com/jxskiss/gopkg/v2/internal/unsafeheader" 11 ) 12 13 // HumanFriendly is a config which generates data that is more friendly 14 // for human reading. 15 // Also, this config can encode data with `interface{}` as map keys, 16 // in contrast, the standard library fails in this case. 17 var HumanFriendly = struct { 18 Marshal func(v any) ([]byte, error) 19 MarshalToString func(v any) (string, error) 20 MarshalIndent func(v any, prefix, indent string) ([]byte, error) 21 MarshalIndentString func(v any, prefix, indent string) (string, error) 22 NewEncoder func(w io.Writer) *Encoder 23 }{ 24 Marshal: hFriendlyMarshal, 25 MarshalToString: hFriendlyMarshalToString, 26 MarshalIndent: hFriendlyMarshalIndent, 27 MarshalIndentString: hFriendlyMarshalIndentString, 28 NewEncoder: newHumanFriendlyEncoder, 29 } 30 31 var jsoniterHumanFriendlyConfig = jsoniter.Config{ 32 EscapeHTML: false, 33 MarshalFloatWith6Digits: true, 34 SortMapKeys: true, 35 UseNumber: true, 36 ObjectFieldMustBeSimpleString: true, 37 }.Froze() 38 39 func hFriendlyMarshal(v any) ([]byte, error) { 40 return jsoniterHumanFriendlyConfig.Marshal(v) 41 } 42 43 func hFriendlyMarshalToString(v any) (string, error) { 44 return jsoniterHumanFriendlyConfig.MarshalToString(v) 45 } 46 47 func hFriendlyMarshalIndent(v any, prefix, indent string) ([]byte, error) { 48 b, err := jsoniterHumanFriendlyConfig.Marshal(v) 49 if err != nil { 50 return nil, err 51 } 52 var buf bytes.Buffer 53 err = json.Indent(&buf, b, prefix, indent) 54 if err != nil { 55 return nil, err 56 } 57 return buf.Bytes(), nil 58 } 59 60 func hFriendlyMarshalIndentString(v any, prefix, indent string) (string, error) { 61 buf, err := hFriendlyMarshalIndent(v, prefix, indent) 62 if err != nil { 63 return "", err 64 } 65 return unsafeheader.BytesToString(buf), nil 66 } 67 68 func newHumanFriendlyEncoder(w io.Writer) *Encoder { 69 return &Encoder{&hFriendlyEncoder{w: w}} 70 } 71 72 type hFriendlyEncoder struct { 73 w io.Writer 74 prefix string 75 indent string 76 } 77 78 func (h *hFriendlyEncoder) Encode(val any) error { 79 var buf []byte 80 var err error 81 if h.prefix == "" && h.indent == "" { 82 buf, err = jsoniterHumanFriendlyConfig.Marshal(val) 83 } else { 84 buf, err = hFriendlyMarshalIndent(val, h.prefix, h.indent) 85 } 86 if err != nil { 87 return err 88 } 89 _, err = h.w.Write(buf) 90 return err 91 } 92 93 func (h *hFriendlyEncoder) SetEscapeHTML(_ bool) { 94 return 95 } 96 97 func (h *hFriendlyEncoder) SetIndent(prefix, indent string) { 98 h.prefix = prefix 99 h.indent = indent 100 }