mirror of
https://github.com/therootcompany/golib.git
synced 2025-10-07 01:28:19 +00:00
feat(colorsync): hard fork for maintenance
This commit is contained in:
parent
5eb3592744
commit
535bf2f824
22
colorjson/LICENSE
Normal file
22
colorjson/LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Tyler Brock
|
||||||
|
Copyright (c) 2025 AJ ONeal
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
65
colorjson/README.md
Normal file
65
colorjson/README.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# ColorJSON: The Fast Color JSON Marshaller for Go
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What is this?
|
||||||
|
|
||||||
|
This package is based heavily on hokaccha/go-prettyjson but has some noticeable differences:
|
||||||
|
|
||||||
|
- Over twice as fast (recursive descent serialization uses buffer instead of string concatenation)
|
||||||
|
```
|
||||||
|
BenchmarkColorJSONMarshall-4 500000 2498 ns/op
|
||||||
|
BenchmarkPrettyJSON-4 200000 6145 ns/op
|
||||||
|
```
|
||||||
|
- more customizable (ability to have zero indent, print raw json strings, etc...)
|
||||||
|
- better defaults (less bold colors)
|
||||||
|
|
||||||
|
ColorJSON was built in order to produce fast beautiful colorized JSON output for [Saw](http://github.com/TylerBrock/saw).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go get -u github.com/therootcompany/golib/colorjson
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Setup
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/therootcompany/golib/colorjson"
|
||||||
|
|
||||||
|
str := `{
|
||||||
|
"str": "foo",
|
||||||
|
"num": 100,
|
||||||
|
"bool": false,
|
||||||
|
"null": null,
|
||||||
|
"array": ["foo", "bar", "baz"],
|
||||||
|
"obj": { "a": 1, "b": 2 }
|
||||||
|
}`
|
||||||
|
|
||||||
|
// Create an intersting JSON object to marshal in a pretty format
|
||||||
|
var obj map[string]interface{}
|
||||||
|
json.Unmarshal([]byte(str), &obj)
|
||||||
|
```
|
||||||
|
|
||||||
|
Vanilla Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
s, _ := colorjson.Marshal(obj)
|
||||||
|
fmt.Println(string(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
Customization (Custom Indent)
|
||||||
|
|
||||||
|
```go
|
||||||
|
f := colorjson.NewFormatter()
|
||||||
|
f.Indent = 2
|
||||||
|
|
||||||
|
s, _ := f.Marshal(v)
|
||||||
|
fmt.Println(string(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This is a fork of <https://github.com/TylerBrock/colorjson> for maintenance.
|
39
colorjson/benchmarks/colorjson_test.go
Normal file
39
colorjson/benchmarks/colorjson_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package colorjson_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/therootcompany/golib/colorjson"
|
||||||
|
"github.com/hokaccha/go-prettyjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func benchmarkMarshall(i int, b *testing.B) {
|
||||||
|
simpleMap := make(map[string]interface{})
|
||||||
|
simpleMap["a"] = 1
|
||||||
|
simpleMap["b"] = "bee"
|
||||||
|
simpleMap["c"] = [3]float64{1, 2, 3}
|
||||||
|
simpleMap["d"] = [3]string{"one", "two", "three"}
|
||||||
|
|
||||||
|
// run the Fib function b.N times
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
colorjson.Marshal(simpleMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPrettyJSON(i int, b *testing.B) {
|
||||||
|
simpleMap := make(map[string]interface{})
|
||||||
|
simpleMap["a"] = 1
|
||||||
|
simpleMap["b"] = "bee"
|
||||||
|
simpleMap["c"] = [3]float64{1, 2, 3}
|
||||||
|
simpleMap["d"] = [3]string{"one", "two", "three"}
|
||||||
|
|
||||||
|
// run the Fib function b.N times
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
prettyjson.Marshal(simpleMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMarshall(b *testing.B) { benchmarkMarshall(100, b) }
|
||||||
|
func BenchmarkMarshall1k(b *testing.B) { benchmarkMarshall(1000, b) }
|
||||||
|
func BenchmarkPrettyJSON(b *testing.B) { benchmarkPrettyJSON(100, b) }
|
||||||
|
func BenchmarkPrettyJSON1k(b *testing.B) { benchmarkPrettyJSON(1000, b) }
|
15
colorjson/benchmarks/go.mod
Normal file
15
colorjson/benchmarks/go.mod
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module github.com/therootcompany/golib/colorjson/benchmarks
|
||||||
|
|
||||||
|
go 1.18.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/therootcompany/golib/colorjson v0.0.0-20200706003622-8a50f05110d2
|
||||||
|
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
)
|
171
colorjson/colorjson.go
Normal file
171
colorjson/colorjson.go
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package colorjson
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
const initialDepth = 0
|
||||||
|
const valueSep = ","
|
||||||
|
const null = "null"
|
||||||
|
const startMap = "{"
|
||||||
|
const endMap = "}"
|
||||||
|
const startArray = "["
|
||||||
|
const endArray = "]"
|
||||||
|
|
||||||
|
const emptyMap = startMap + endMap
|
||||||
|
const emptyArray = startArray + endArray
|
||||||
|
|
||||||
|
type Formatter struct {
|
||||||
|
KeyColor *color.Color
|
||||||
|
StringColor *color.Color
|
||||||
|
BoolColor *color.Color
|
||||||
|
NumberColor *color.Color
|
||||||
|
NullColor *color.Color
|
||||||
|
StringMaxLength int
|
||||||
|
Indent int
|
||||||
|
DisabledColor bool
|
||||||
|
RawStrings bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFormatter() *Formatter {
|
||||||
|
return &Formatter{
|
||||||
|
KeyColor: color.New(color.FgWhite),
|
||||||
|
StringColor: color.New(color.FgGreen),
|
||||||
|
BoolColor: color.New(color.FgYellow),
|
||||||
|
NumberColor: color.New(color.FgCyan),
|
||||||
|
NullColor: color.New(color.FgMagenta),
|
||||||
|
StringMaxLength: 0,
|
||||||
|
DisabledColor: false,
|
||||||
|
Indent: 0,
|
||||||
|
RawStrings: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) sprintfColor(c *color.Color, format string, args ...interface{}) string {
|
||||||
|
if f.DisabledColor || c == nil {
|
||||||
|
return fmt.Sprintf(format, args...)
|
||||||
|
}
|
||||||
|
return c.SprintfFunc()(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) sprintColor(c *color.Color, s string) string {
|
||||||
|
if f.DisabledColor || c == nil {
|
||||||
|
return fmt.Sprint(s)
|
||||||
|
}
|
||||||
|
return c.SprintFunc()(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) writeIndent(buf *bytes.Buffer, depth int) {
|
||||||
|
buf.WriteString(strings.Repeat(" ", f.Indent*depth))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) writeObjSep(buf *bytes.Buffer) {
|
||||||
|
if f.Indent != 0 {
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
} else {
|
||||||
|
buf.WriteByte(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) Marshal(jsonObj interface{}) ([]byte, error) {
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
f.marshalValue(jsonObj, &buffer, initialDepth)
|
||||||
|
return buffer.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) marshalMap(m map[string]interface{}, buf *bytes.Buffer, depth int) {
|
||||||
|
remaining := len(m)
|
||||||
|
|
||||||
|
if remaining == 0 {
|
||||||
|
buf.WriteString(emptyMap)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := make([]string, 0)
|
||||||
|
for key := range m {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
buf.WriteString(startMap)
|
||||||
|
f.writeObjSep(buf)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
f.writeIndent(buf, depth+1)
|
||||||
|
buf.WriteString(f.KeyColor.Sprintf("\"%s\": ", key))
|
||||||
|
f.marshalValue(m[key], buf, depth+1)
|
||||||
|
remaining--
|
||||||
|
if remaining != 0 {
|
||||||
|
buf.WriteString(valueSep)
|
||||||
|
}
|
||||||
|
f.writeObjSep(buf)
|
||||||
|
}
|
||||||
|
f.writeIndent(buf, depth)
|
||||||
|
buf.WriteString(endMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) marshalArray(a []interface{}, buf *bytes.Buffer, depth int) {
|
||||||
|
if len(a) == 0 {
|
||||||
|
buf.WriteString(emptyArray)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString(startArray)
|
||||||
|
f.writeObjSep(buf)
|
||||||
|
|
||||||
|
for i, v := range a {
|
||||||
|
f.writeIndent(buf, depth+1)
|
||||||
|
f.marshalValue(v, buf, depth+1)
|
||||||
|
if i < len(a)-1 {
|
||||||
|
buf.WriteString(valueSep)
|
||||||
|
}
|
||||||
|
f.writeObjSep(buf)
|
||||||
|
}
|
||||||
|
f.writeIndent(buf, depth)
|
||||||
|
buf.WriteString(endArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) marshalValue(val interface{}, buf *bytes.Buffer, depth int) {
|
||||||
|
switch v := val.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
f.marshalMap(v, buf, depth)
|
||||||
|
case []interface{}:
|
||||||
|
f.marshalArray(v, buf, depth)
|
||||||
|
case string:
|
||||||
|
f.marshalString(v, buf)
|
||||||
|
case float64:
|
||||||
|
buf.WriteString(f.sprintColor(f.NumberColor, strconv.FormatFloat(v, 'f', -1, 64)))
|
||||||
|
case bool:
|
||||||
|
buf.WriteString(f.sprintColor(f.BoolColor, (strconv.FormatBool(v))))
|
||||||
|
case nil:
|
||||||
|
buf.WriteString(f.sprintColor(f.NullColor, null))
|
||||||
|
case json.Number:
|
||||||
|
buf.WriteString(f.sprintColor(f.NumberColor, v.String()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) marshalString(str string, buf *bytes.Buffer) {
|
||||||
|
if !f.RawStrings {
|
||||||
|
strBytes, _ := json.Marshal(str)
|
||||||
|
str = string(strBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.StringMaxLength != 0 && len(str) >= f.StringMaxLength {
|
||||||
|
str = fmt.Sprintf("%s...", str[0:f.StringMaxLength])
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString(f.sprintColor(f.StringColor, str))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal JSON data with default options
|
||||||
|
func Marshal(jsonObj interface{}) ([]byte, error) {
|
||||||
|
return NewFormatter().Marshal(jsonObj)
|
||||||
|
}
|
30
colorjson/examples/indent/main.go
Normal file
30
colorjson/examples/indent/main.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/therootcompany/golib/colorjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := `{
|
||||||
|
"str": "foo",
|
||||||
|
"num": 100,
|
||||||
|
"bool": false,
|
||||||
|
"null": null,
|
||||||
|
"array": ["foo", "bar", "baz"],
|
||||||
|
"obj": { "a": 1, "b": 2 }
|
||||||
|
}`
|
||||||
|
|
||||||
|
var obj map[string]interface{}
|
||||||
|
json.Unmarshal([]byte(str), &obj)
|
||||||
|
|
||||||
|
// Make a custom formatter with indent set
|
||||||
|
f := colorjson.NewFormatter()
|
||||||
|
f.Indent = 4
|
||||||
|
|
||||||
|
// Marshall the Colorized JSON
|
||||||
|
s, _ := f.Marshal(obj)
|
||||||
|
fmt.Println(string(s))
|
||||||
|
}
|
26
colorjson/examples/simple/main.go
Normal file
26
colorjson/examples/simple/main.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/therootcompany/golib/colorjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := `{
|
||||||
|
"str": "foo",
|
||||||
|
"num": 100,
|
||||||
|
"bool": false,
|
||||||
|
"null": null,
|
||||||
|
"array": ["foo", "bar", "baz"],
|
||||||
|
"obj": { "a": 1, "b": 2 }
|
||||||
|
}`
|
||||||
|
|
||||||
|
var obj map[string]interface{}
|
||||||
|
json.Unmarshal([]byte(str), &obj)
|
||||||
|
|
||||||
|
// Marshall the Colorized JSON
|
||||||
|
s, _ := colorjson.Marshal(obj)
|
||||||
|
fmt.Println(string(s))
|
||||||
|
}
|
11
colorjson/go.mod
Normal file
11
colorjson/go.mod
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module github.com/therootcompany/golib/colorjson
|
||||||
|
|
||||||
|
go 1.18.0
|
||||||
|
|
||||||
|
require github.com/fatih/color v1.18.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
)
|
11
colorjson/go.sum
Normal file
11
colorjson/go.sum
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
Loading…
x
Reference in New Issue
Block a user