96 lines
1.7 KiB
Go
96 lines
1.7 KiB
Go
package jsoncolor
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
colorDelim = "1;38" // bright white
|
|
colorKey = "1;34" // bright blue
|
|
colorNull = "1;30" // gray
|
|
colorString = "32" // green
|
|
colorBool = "33" // yellow
|
|
)
|
|
|
|
// Write colorized JSON output parsed from reader
|
|
func Write(w io.Writer, r io.Reader, indent string) error {
|
|
dec := json.NewDecoder(r)
|
|
dec.UseNumber()
|
|
|
|
var idx int
|
|
var stack []json.Delim
|
|
|
|
for {
|
|
t, err := dec.Token()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch tt := t.(type) {
|
|
case json.Delim:
|
|
switch tt {
|
|
case '{', '[':
|
|
stack = append(stack, tt)
|
|
idx = 0
|
|
fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", colorDelim, tt)
|
|
if dec.More() {
|
|
fmt.Fprint(w, "\n", strings.Repeat(indent, len(stack)))
|
|
}
|
|
continue
|
|
case '}', ']':
|
|
stack = stack[:len(stack)-1]
|
|
idx = 0
|
|
fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", colorDelim, tt)
|
|
}
|
|
default:
|
|
b, err := json.Marshal(tt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
isKey := len(stack) > 0 && stack[len(stack)-1] == '{' && idx%2 == 0
|
|
idx++
|
|
|
|
var color string
|
|
if isKey {
|
|
color = colorKey
|
|
} else if tt == nil {
|
|
color = colorNull
|
|
} else {
|
|
switch t.(type) {
|
|
case string:
|
|
color = colorString
|
|
case bool:
|
|
color = colorBool
|
|
}
|
|
}
|
|
|
|
if color == "" {
|
|
_, _ = w.Write(b)
|
|
} else {
|
|
fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", color, b)
|
|
}
|
|
|
|
if isKey {
|
|
fmt.Fprintf(w, "\x1b[%sm:\x1b[m ", colorDelim)
|
|
continue
|
|
}
|
|
}
|
|
|
|
if dec.More() {
|
|
fmt.Fprintf(w, "\x1b[%sm,\x1b[m\n%s", colorDelim, strings.Repeat(indent, len(stack)))
|
|
} else if len(stack) > 0 {
|
|
fmt.Fprint(w, "\n", strings.Repeat(indent, len(stack)-1))
|
|
} else {
|
|
fmt.Fprint(w, "\n")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|