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  }