cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

main
012 / internal / nuon / json.go
json.go 2.0K
1package nuon23import (4 "fmt"5 "math"6 "strconv"7 "strings"8 "unicode/utf8"9)1011// AppendJSON appends v to b as nushell's `to json` writes it: sizes as12// bytes, durations as nanoseconds, dates as RFC 3339 strings, binary as13// a list of byte values, and infinities and NaN as null.14func AppendJSON(b []byte, v Value) []byte {15 switch v.Kind {16 case Null:17 return append(b, "null"...)18 case Bool:19 return strconv.AppendBool(b, v.Bool)20 case Int, Filesize, Duration:21 return strconv.AppendInt(b, v.Int, 10)22 case Float:23 if math.IsNaN(v.Float) || math.IsInf(v.Float, 0) {24 return append(b, "null"...)25 }26 return appendFloat(b, v.Float)27 case String:28 return appendJSONString(b, v.Str)29 case Date:30 return append(appendDate(append(b, '"'), v.Time), '"')31 case Binary:32 b = append(b, '[')33 for i, c := range v.Bytes {34 if i > 0 {35 b = append(b, ',')36 }37 b = strconv.AppendUint(b, uint64(c), 10)38 }39 return append(b, ']')40 case List:41 b = append(b, '[')42 for i, item := range v.List {43 if i > 0 {44 b = append(b, ',')45 }46 b = AppendJSON(b, item)47 }48 return append(b, ']')49 case Record:50 return AppendJSONRecord(b, v.Fields)51 }52 return b53}5455// AppendJSONRecord appends fields as a JSON object, in order.56func AppendJSONRecord(b []byte, fs []Field) []byte {57 b = append(b, '{')58 for i, f := range fs {59 if i > 0 {60 b = append(b, ',')61 }62 b = appendJSONString(b, f.Key)63 b = append(b, ':')64 b = AppendJSON(b, f.Value)65 }66 return append(b, '}')67}6869// appendJSONString quotes s for JSON, escaping only what JSON needs.70func appendJSONString(b []byte, s string) []byte {71 b = append(b, '"')72 for _, r := range strings.ToValidUTF8(s, "�") {73 switch {74 case r == '"' || r == '\\':75 b = append(b, '\\', byte(r))76 case r == '\n':77 b = append(b, `\n`...)78 case r == '\r':79 b = append(b, `\r`...)80 case r == '\t':81 b = append(b, `\t`...)82 case r < 0x20:83 b = append(b, fmt.Sprintf(`\u%04x`, r)...)84 default:85 b = utf8.AppendRune(b, r)86 }87 }88 return append(b, '"')89}