github.com/neilotoole/jsoncolor@v0.7.2-0.20231115150201-1637fae69be1/README.md (about)

     1  [![Actions Status](https://github.com/neilotoole/jsoncolor/workflows/Go/badge.svg)](https://github.com/neilotoole/jsoncolor/actions?query=workflow%3AGo)
     2  [![Go Report Card](https://goreportcard.com/badge/neilotoole/jsoncolor)](https://goreportcard.com/report/neilotoole/jsoncolor)
     3  [![release](https://img.shields.io/badge/release-v0.7.0-green.svg)](https://github.com/neilotoole/jsoncolor/releases/tag/v0.7.0)
     4  [![Go Reference](https://pkg.go.dev/badge/github.com/neilotoole/jsoncolor.svg)](https://pkg.go.dev/github.com/neilotoole/jsoncolor)
     5  [![license](https://img.shields.io/github/license/neilotoole/jsoncolor)](./LICENSE)
     6  
     7  # jsoncolor
     8  
     9  Package `neilotoole/jsoncolor` is a drop-in replacement for stdlib
    10  [`encoding/json`](https://pkg.go.dev/encoding/json) that outputs colorized JSON.
    11  
    12  Why? Well, [`jq`](https://jqlang.github.io/jq/) colorizes its output by default, and color output
    13  is desirable for many Go CLIs. This package performs colorization (and indentation) inline
    14  in the encoder, and is significantly faster than stdlib at indentation.
    15  
    16  From the example [`jc`](./cmd/jc/main.go) app:
    17  
    18  ![jsoncolor-output](./splash.png)
    19  
    20  ## Usage
    21  
    22  Get the package per the normal mechanism (requires Go 1.16+):
    23  
    24  ```shell
    25  go get -u github.com/neilotoole/jsoncolor
    26  ```
    27  
    28  Then:
    29  
    30  ```go
    31  package main
    32  
    33  import (
    34    "fmt"
    35    "github.com/mattn/go-colorable"
    36    json "github.com/neilotoole/jsoncolor"
    37    "os"
    38  )
    39  
    40  func main() {
    41    var enc *json.Encoder
    42  
    43    // Note: this check will fail if running inside Goland (and
    44    // other IDEs?) as IsColorTerminal will return false.
    45    if json.IsColorTerminal(os.Stdout) {
    46      // Safe to use color
    47      out := colorable.NewColorable(os.Stdout) // needed for Windows
    48      enc = json.NewEncoder(out)
    49  
    50      // DefaultColors are similar to jq
    51      clrs := json.DefaultColors()
    52  
    53      // Change some values, just for fun
    54      clrs.Bool = json.Color("\x1b[36m") // Change the bool color
    55      clrs.String = json.Color{}         // Disable the string color
    56  
    57      enc.SetColors(clrs)
    58    } else {
    59      // Can't use color; but the encoder will still work
    60      enc = json.NewEncoder(os.Stdout)
    61    }
    62  
    63    m := map[string]interface{}{
    64      "a": 1,
    65      "b": true,
    66      "c": "hello",
    67    }
    68  
    69    if err := enc.Encode(m); err != nil {
    70      fmt.Fprintln(os.Stderr, err)
    71      os.Exit(1)
    72    }
    73  }
    74  ```
    75  
    76  ### Configuration
    77  
    78  To enable colorization, invoke [`enc.SetColors`](https://pkg.go.dev/github.com/neilotoole/jsoncolor#Encoder.SetColors).
    79  
    80  The [`Colors`](https://pkg.go.dev/github.com/neilotoole/jsoncolor#Colors) struct
    81  holds color config. The zero value and `nil` are both safe for use (resulting in no colorization).
    82  
    83  The [`DefaultColors`](https://pkg.go.dev/github.com/neilotoole/jsoncolor#DefaultColors) func
    84  returns a `Colors` struct that produces results similar to `jq`:
    85  
    86  ```go
    87  // DefaultColors returns the default Colors configuration.
    88  // These colors largely follow jq's default colorization,
    89  // with some deviation.
    90  func DefaultColors() *Colors {
    91    return &Colors{
    92      Null:   Color("\x1b[2m"),
    93      Bool:   Color("\x1b[1m"),
    94      Number: Color("\x1b[36m"),
    95      String: Color("\x1b[32m"),
    96      Key:    Color("\x1b[34;1m"),
    97      Bytes:  Color("\x1b[2m"),
    98      Time:   Color("\x1b[32;2m"),
    99      Punc:   Color{}, // No colorization
   100    }
   101  }
   102  ```
   103  
   104  As seen above, use the `Color` zero value (`Color{}`) to
   105  disable colorization for that JSON element.
   106  
   107  ### Helper for `fatih/color`
   108  
   109  It can be inconvenient to use terminal codes, e.g. `json.Color("\x1b[36m")`.
   110  A helper package provides an adapter for [`fatih/color`](https://github.com/fatih/color).
   111  
   112  ```go
   113    // import "github.com/neilotoole/jsoncolor/helper/fatihcolor"
   114    // import "github.com/fatih/color"
   115    // import "github.com/mattn/go-colorable"
   116    
   117    out := colorable.NewColorable(os.Stdout) // needed for Windows
   118    enc = json.NewEncoder(out)
   119    
   120    fclrs := fatihcolor.DefaultColors()
   121    // Change some values, just for fun
   122    fclrs.Number = color.New(color.FgBlue)
   123    fclrs.String = color.New(color.FgCyan)
   124    
   125    clrs := fatihcolor.ToCoreColors(fclrs)
   126    enc.SetColors(clrs)
   127  ```
   128  
   129  ### Drop-in for `encoding/json`
   130  
   131  This package is a full drop-in for stdlib [`encoding/json`](https://pkg.go.dev/encoding/json)
   132  (thanks to the ancestral [`segmentio/encoding/json`](https://pkg.go.dev/github.com/segmentio/encoding/json)
   133  pkg being a full drop-in).
   134  
   135  To drop-in, just use an import alias:
   136  
   137  ```go
   138    import json "github.com/neilotoole/jsoncolor"
   139  ```
   140  
   141  ## Example app: `jc`
   142  
   143  See [`cmd/jc`](cmd/jc/main.go) for a trivial CLI implementation that can accept JSON input,
   144  and output that JSON in color.
   145  
   146  ```shell
   147  # From project root
   148  $ go install ./cmd/jc
   149  $ cat ./testdata/sakila_actor.json | jc
   150  ```
   151  
   152  ## Benchmarks
   153  
   154  Note that this package contains [`golang_bench_test.go`](./golang_bench_test.go), which
   155  is inherited from `segmentj`. But here we're interested in [`benchmark_test.go:BenchmarkEncode`](./benchmark_test.go),
   156  which benchmarks encoding performance versus other JSON encoder packages.
   157  The results below benchmark the following:
   158  
   159  - Stdlib [`encoding/json`](https://pkg.go.dev/encoding/json) (`go1.17.1`).
   160  - [`segmentj`](https://github.com/segmentio/encoding): `v0.1.14`, which was when `jsoncolor` was forked. The newer `segmentj` code performs even better.
   161  - `neilotoole/jsoncolor`: (this package) `v0.6.0`.
   162  - [`nwidger/jsoncolor`](https://github.com/nwidger/jsoncolor): `v0.3.0`, latest at time of benchmarks.
   163  
   164  Note that two other Go JSON colorization packages ([`hokaccha/go-prettyjson`](https://github.com/hokaccha/go-prettyjson) and
   165  [`TylerBrock/colorjson`](https://github.com/TylerBrock/colorjson)) are excluded from
   166  these benchmarks because they do not provide a stdlib-compatible `Encoder` impl.
   167  
   168  ```
   169  $ go test -bench=BenchmarkEncode -benchtime="5s"
   170  goarch: amd64
   171  pkg: github.com/neilotoole/jsoncolor
   172  cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
   173  BenchmarkEncode/stdlib_NoIndent-16                           181          33047390 ns/op         8870685 B/op     120022 allocs/op
   174  BenchmarkEncode/stdlib_Indent-16                             124          48093178 ns/op        10470366 B/op     120033 allocs/op
   175  BenchmarkEncode/segmentj_NoIndent-16                         415          14658699 ns/op         3788911 B/op      10020 allocs/op
   176  BenchmarkEncode/segmentj_Indent-16                           195          30628798 ns/op         5404492 B/op      10025 allocs/op
   177  BenchmarkEncode/neilotoole_NoIndent_NoColor-16               362          16522399 ns/op         3789034 B/op      10020 allocs/op
   178  BenchmarkEncode/neilotoole_Indent_NoColor-16                 303          20146856 ns/op         5460753 B/op      10021 allocs/op
   179  BenchmarkEncode/neilotoole_NoIndent_Color-16                 295          19989420 ns/op        10326019 B/op      10029 allocs/op
   180  BenchmarkEncode/neilotoole_Indent_Color-16                   246          24714163 ns/op        11996890 B/op      10030 allocs/op
   181  BenchmarkEncode/nwidger_NoIndent_NoColor-16                   10         541107983 ns/op        92934231 B/op    4490210 allocs/op
   182  BenchmarkEncode/nwidger_Indent_NoColor-16                      7         798088086 ns/op        117258321 B/op   6290213 allocs/op
   183  BenchmarkEncode/nwidger_indent_NoIndent_Colo-16               10         542002051 ns/op        92935639 B/op    4490224 allocs/op
   184  BenchmarkEncode/nwidger_indent_Indent_Color-16                 7         799928353 ns/op        117259195 B/op   6290220 allocs/op
   185  ```
   186  
   187  As always, take benchmarks with a large grain of salt, as they're based on a (small) synthetic benchmark.
   188  More benchmarks would give a better picture (and note as well that the benchmarked `segmentj` is an older version, `v0.1.14`).
   189  
   190  All that having been said, what can we surmise from these particular results?
   191  
   192  - `segmentj` performs better than `stdlib` at all encoding tasks.
   193  - `jsoncolor` performs better than `segmentj` for indentation (which makes sense, as indentation is performed inline).
   194  - `jsoncolor` performs better than `stdlib` at all encoding tasks.
   195  
   196  Again, trust these benchmarks at your peril. Create your own benchmarks for your own workload.
   197  
   198  ## Notes
   199  
   200  - The [`.golangci.yml`](./.golangci.yml) linter settings have been fiddled with to hush some
   201    linting issues inherited from the `segmentio` codebase at the time of forking. Thus, the linter report
   202    may not be of great use. In an ideal world, the `jsoncolor` functionality would be [ported](https://github.com/neilotoole/jsoncolor/issues/15) to a
   203    more recent (and better-linted) version of the `segementio` codebase.
   204  - The `segmentio` encoder (at least as of `v0.1.14`) encodes `time.Duration` as string, while `stdlib` outputs as `int64`.
   205    This package follows `stdlib`.
   206  - The [`Colors.Punc`](https://pkg.go.dev/github.com/neilotoole/jsoncolor#Colors) field controls all
   207    punctuation colorization, i.e. `[]{},:"`. It is probably worthwhile to [separate](https://github.com/neilotoole/jsoncolor/issues/16)
   208    these out into individually-configurable elements.
   209  
   210  <a name="history"></a>
   211  ## CHANGELOG
   212  
   213  History: this package is an extract of [`sq`](https://github.com/neilotoole/sq)'s JSON encoding package, which itself is a fork of the
   214  [`segmentio/encoding`](https://github.com/segmentio/encoding) JSON encoding package. Note that the
   215  original `sq` JSON encoder was forked from Segment's codebase at `v0.1.14`, so
   216  the codebases have drifted significantly by now.
   217  
   218  ### [v0.7.1](https://github.com/neilotoole/jsoncolor/releases/tag/v0.7.1)
   219  
   220  - [#27](https://github.com/neilotoole/jsoncolor/pull/27): Improved Windows terminal color support checking.
   221  
   222  ### [v0.7.0](https://github.com/neilotoole/jsoncolor/releases/tag/v0.7.0)
   223  
   224  - [#21](https://github.com/neilotoole/jsoncolor/pull/21): Support for [`encoding.TextMarshaler`](https://pkg.go.dev/encoding#TextMarshaler).
   225  - [#22](https://github.com/neilotoole/jsoncolor/pull/22): Removed redundant dependencies.
   226  - [#26](https://github.com/neilotoole/jsoncolor/pull/26): Updated dependencies.
   227  
   228  ## Acknowledgments
   229  
   230  - [`jq`](https://stedolan.github.io/jq/): sine qua non.
   231  - [`segmentio/encoding`](https://github.com/segmentio/encoding): `jsoncolor` is layered into Segment's JSON encoder. They did the hard work. Much gratitude to that team.
   232  - [`sq`](https://github.com/neilotoole/sq): `jsoncolor` is effectively an extract of code created specifically for `sq`.
   233  - [`mattn/go-colorable`](https://github.com/mattn/go-colorable): no project is complete without `mattn` having played a role.
   234  - [`fatih/color`](https://github.com/fatih/color): the color library.
   235  - [`@hermannm`](https://github.com/hermannm): for several PRs.
   236  
   237  ### Related
   238  
   239  - [`nwidger/jsoncolor`](https://github.com/nwidger/jsoncolor)
   240  - [`hokaccha/go-prettyjson`](https://github.com/hokaccha/go-prettyjson)
   241  - [`TylerBrock/colorjson`](https://github.com/TylerBrock/colorjson)