json.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /**
  2. COPY https://github.com/hokaccha/go-prettyjson/blob/master/prettyjson.go
  3. */
  4. // Package prettyjson provides JSON pretty print.
  5. package prettyjson
  6. import (
  7. "bytes"
  8. "encoding/json"
  9. "fmt"
  10. "sort"
  11. "strconv"
  12. "strings"
  13. "github.com/fatih/color"
  14. )
  15. // Formatter is a struct to format JSON data. `color` is github.com/fatih/color: https://github.com/fatih/color
  16. type Formatter struct {
  17. // JSON key color. Default is `color.New(color.FgBlue, color.Bold)`.
  18. KeyColor *color.Color
  19. // JSON string value color. Default is `color.New(color.FgGreen, color.Bold)`.
  20. StringColor *color.Color
  21. // JSON boolean value color. Default is `color.New(color.FgYellow, color.Bold)`.
  22. BoolColor *color.Color
  23. // JSON number value color. Default is `color.New(color.FgCyan, color.Bold)`.
  24. NumberColor *color.Color
  25. // JSON null value color. Default is `color.New(color.FgBlack, color.Bold)`.
  26. NullColor *color.Color
  27. // Max length of JSON string value. When the value is 1 and over, string is truncated to length of the value.
  28. // Default is 0 (not truncated).
  29. StringMaxLength int
  30. // Boolean to disable color. Default is false.
  31. DisabledColor bool
  32. // Indent space number. Default is 2.
  33. Indent int
  34. // Newline string. To print without new lines set it to empty string. Default is \n.
  35. Newline string
  36. }
  37. // NewFormatter returns a new formatter with following default values.
  38. func NewFormatter() *Formatter {
  39. return &Formatter{
  40. KeyColor: color.New(color.FgBlue, color.Bold),
  41. StringColor: color.New(color.FgGreen, color.Bold),
  42. BoolColor: color.New(color.FgYellow, color.Bold),
  43. NumberColor: color.New(color.FgCyan, color.Bold),
  44. NullColor: color.New(color.FgBlack, color.Bold),
  45. StringMaxLength: 0,
  46. DisabledColor: false,
  47. Indent: 2,
  48. Newline: "\n",
  49. }
  50. }
  51. // Marshal marshals and formats JSON data.
  52. func (f *Formatter) Marshal(v interface{}) ([]byte, error) {
  53. data, err := json.Marshal(v)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return f.Format(data)
  58. }
  59. // Format formats JSON string.
  60. func (f *Formatter) Format(data []byte) ([]byte, error) {
  61. var v interface{}
  62. decoder := json.NewDecoder(bytes.NewReader(data))
  63. decoder.UseNumber()
  64. if err := decoder.Decode(&v); err != nil {
  65. return nil, err
  66. }
  67. return []byte(f.pretty(v, 1)), nil
  68. }
  69. func (f *Formatter) sprintfColor(c *color.Color, format string, args ...interface{}) string {
  70. if f.DisabledColor || c == nil {
  71. return fmt.Sprintf(format, args...)
  72. }
  73. return c.SprintfFunc()(format, args...)
  74. }
  75. func (f *Formatter) sprintColor(c *color.Color, s string) string {
  76. if f.DisabledColor || c == nil {
  77. return fmt.Sprint(s)
  78. }
  79. return c.SprintFunc()(s)
  80. }
  81. func (f *Formatter) pretty(v interface{}, depth int) string {
  82. switch val := v.(type) {
  83. case string:
  84. return f.processString(val)
  85. case float64:
  86. return f.sprintColor(f.NumberColor, strconv.FormatFloat(val, 'f', -1, 64))
  87. case json.Number:
  88. return f.sprintColor(f.NumberColor, string(val))
  89. case bool:
  90. return f.sprintColor(f.BoolColor, strconv.FormatBool(val))
  91. case nil:
  92. return f.sprintColor(f.NullColor, "null")
  93. case map[string]interface{}:
  94. return f.processMap(val, depth)
  95. case []interface{}:
  96. return f.processArray(val, depth)
  97. }
  98. return ""
  99. }
  100. func (f *Formatter) processString(s string) string {
  101. r := []rune(s)
  102. if f.StringMaxLength != 0 && len(r) >= f.StringMaxLength {
  103. s = string(r[0:f.StringMaxLength]) + "..."
  104. }
  105. buf := &bytes.Buffer{}
  106. encoder := json.NewEncoder(buf)
  107. encoder.SetEscapeHTML(false)
  108. encoder.Encode(s)
  109. s = string(buf.Bytes())
  110. s = strings.TrimSuffix(s, "\n")
  111. return f.sprintColor(f.StringColor, s)
  112. }
  113. func (f *Formatter) processMap(m map[string]interface{}, depth int) string {
  114. if len(m) == 0 {
  115. return "{}"
  116. }
  117. currentIndent := f.generateIndent(depth - 1)
  118. nextIndent := f.generateIndent(depth)
  119. rows := []string{}
  120. keys := []string{}
  121. for key := range m {
  122. keys = append(keys, key)
  123. }
  124. sort.Strings(keys)
  125. for _, key := range keys {
  126. val := m[key]
  127. buf := &bytes.Buffer{}
  128. encoder := json.NewEncoder(buf)
  129. encoder.SetEscapeHTML(false)
  130. encoder.Encode(key)
  131. s := strings.TrimSuffix(string(buf.Bytes()), "\n")
  132. k := f.sprintColor(f.KeyColor, s)
  133. v := f.pretty(val, depth+1)
  134. valueIndent := " "
  135. if f.Newline == "" {
  136. valueIndent = ""
  137. }
  138. row := fmt.Sprintf("%s%s:%s%s", nextIndent, k, valueIndent, v)
  139. rows = append(rows, row)
  140. }
  141. return fmt.Sprintf("{%s%s%s%s}", f.Newline, strings.Join(rows, ","+f.Newline), f.Newline, currentIndent)
  142. }
  143. func (f *Formatter) processArray(a []interface{}, depth int) string {
  144. if len(a) == 0 {
  145. return "[]"
  146. }
  147. currentIndent := f.generateIndent(depth - 1)
  148. nextIndent := f.generateIndent(depth)
  149. rows := []string{}
  150. for _, val := range a {
  151. c := f.pretty(val, depth+1)
  152. row := nextIndent + c
  153. rows = append(rows, row)
  154. }
  155. return fmt.Sprintf("[%s%s%s%s]", f.Newline, strings.Join(rows, ","+f.Newline), f.Newline, currentIndent)
  156. }
  157. func (f *Formatter) generateIndent(depth int) string {
  158. return strings.Repeat(" ", f.Indent*depth)
  159. }
  160. // Marshal JSON data with default options.
  161. func Marshal(v interface{}) ([]byte, error) {
  162. return NewFormatter().Marshal(v)
  163. }
  164. // Format JSON string with default options.
  165. func Format(data []byte) ([]byte, error) {
  166. return NewFormatter().Format(data)
  167. }