jsoncolor

package module
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2023 License: MIT Imports: 21 Imported by: 9

README

Actions Status Go Report Card release Go Reference license

jsoncolor

Package neilotoole/jsoncolor is a drop-in replacement for stdlib encoding/json that outputs colorized JSON.

Why? Well, jq colorizes its output by default, and color output is desirable for many Go CLIs. This package performs colorization (and indentation) inline in the encoder, and is significantly faster than stdlib at indentation.

From the example jc app:

jsoncolor-output

Usage

Get the package per the normal mechanism (requires Go 1.16+):

go get -u github.com/neilotoole/jsoncolor

Then:

package main

import (
  "fmt"
  "github.com/mattn/go-colorable"
  json "github.com/neilotoole/jsoncolor"
  "os"
)

func main() {
  var enc *json.Encoder

  // Note: this check will fail if running inside Goland (and
  // other IDEs?) as IsColorTerminal will return false.
  if json.IsColorTerminal(os.Stdout) {
    // Safe to use color
    out := colorable.NewColorable(os.Stdout) // needed for Windows
    enc = json.NewEncoder(out)

    // DefaultColors are similar to jq
    clrs := json.DefaultColors()

    // Change some values, just for fun
    clrs.Bool = json.Color("\x1b[36m") // Change the bool color
    clrs.String = json.Color{}         // Disable the string color

    enc.SetColors(clrs)
  } else {
    // Can't use color; but the encoder will still work
    enc = json.NewEncoder(os.Stdout)
  }

  m := map[string]interface{}{
    "a": 1,
    "b": true,
    "c": "hello",
  }

  if err := enc.Encode(m); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
  }
}
Configuration

To enable colorization, invoke enc.SetColors.

The Colors struct holds color config. The zero value and nil are both safe for use (resulting in no colorization).

The DefaultColors func returns a Colors struct that produces results similar to jq:

// DefaultColors returns the default Colors configuration.
// These colors largely follow jq's default colorization,
// with some deviation.
func DefaultColors() *Colors {
  return &Colors{
    Null:   Color("\x1b[2m"),
    Bool:   Color("\x1b[1m"),
    Number: Color("\x1b[36m"),
    String: Color("\x1b[32m"),
    Key:    Color("\x1b[34;1m"),
    Bytes:  Color("\x1b[2m"),
    Time:   Color("\x1b[32;2m"),
    Punc:   Color{}, // No colorization
  }
}

As seen above, use the Color zero value (Color{}) to disable colorization for that JSON element.

Helper for fatih/color

It can be inconvenient to use terminal codes, e.g. json.Color("\x1b[36m"). A helper package provides an adapter for fatih/color.

  // import "github.com/neilotoole/jsoncolor/helper/fatihcolor"
  // import "github.com/fatih/color"
  // import "github.com/mattn/go-colorable"
  
  out := colorable.NewColorable(os.Stdout) // needed for Windows
  enc = json.NewEncoder(out)
  
  fclrs := fatihcolor.DefaultColors()
  // Change some values, just for fun
  fclrs.Number = color.New(color.FgBlue)
  fclrs.String = color.New(color.FgCyan)
  
  clrs := fatihcolor.ToCoreColors(fclrs)
  enc.SetColors(clrs)
Drop-in for encoding/json

This package is a full drop-in for stdlib encoding/json (thanks to the ancestral segmentio/encoding/json pkg being a full drop-in).

To drop-in, just use an import alias:

  import json "github.com/neilotoole/jsoncolor"

Example app: jc

See cmd/jc for a trivial CLI implementation that can accept JSON input, and output that JSON in color.

# From project root
$ go install ./cmd/jc
$ cat ./testdata/sakila_actor.json | jc

Benchmarks

Note that this package contains golang_bench_test.go, which is inherited from segmentj. But here we're interested in benchmark_test.go:BenchmarkEncode, which benchmarks encoding performance versus other JSON encoder packages. The results below benchmark the following:

  • Stdlib encoding/json (go1.17.1).
  • segmentj: v0.1.14, which was when jsoncolor was forked. The newer segmentj code performs even better.
  • neilotoole/jsoncolor: (this package) v0.6.0.
  • nwidger/jsoncolor: v0.3.0, latest at time of benchmarks.

Note that two other Go JSON colorization packages (hokaccha/go-prettyjson and TylerBrock/colorjson) are excluded from these benchmarks because they do not provide a stdlib-compatible Encoder impl.

$ go test -bench=BenchmarkEncode -benchtime="5s"
goarch: amd64
pkg: github.com/neilotoole/jsoncolor
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkEncode/stdlib_NoIndent-16                           181          33047390 ns/op         8870685 B/op     120022 allocs/op
BenchmarkEncode/stdlib_Indent-16                             124          48093178 ns/op        10470366 B/op     120033 allocs/op
BenchmarkEncode/segmentj_NoIndent-16                         415          14658699 ns/op         3788911 B/op      10020 allocs/op
BenchmarkEncode/segmentj_Indent-16                           195          30628798 ns/op         5404492 B/op      10025 allocs/op
BenchmarkEncode/neilotoole_NoIndent_NoColor-16               362          16522399 ns/op         3789034 B/op      10020 allocs/op
BenchmarkEncode/neilotoole_Indent_NoColor-16                 303          20146856 ns/op         5460753 B/op      10021 allocs/op
BenchmarkEncode/neilotoole_NoIndent_Color-16                 295          19989420 ns/op        10326019 B/op      10029 allocs/op
BenchmarkEncode/neilotoole_Indent_Color-16                   246          24714163 ns/op        11996890 B/op      10030 allocs/op
BenchmarkEncode/nwidger_NoIndent_NoColor-16                   10         541107983 ns/op        92934231 B/op    4490210 allocs/op
BenchmarkEncode/nwidger_Indent_NoColor-16                      7         798088086 ns/op        117258321 B/op   6290213 allocs/op
BenchmarkEncode/nwidger_indent_NoIndent_Colo-16               10         542002051 ns/op        92935639 B/op    4490224 allocs/op
BenchmarkEncode/nwidger_indent_Indent_Color-16                 7         799928353 ns/op        117259195 B/op   6290220 allocs/op

As always, take benchmarks with a large grain of salt, as they're based on a (small) synthetic benchmark. More benchmarks would give a better picture (and note as well that the benchmarked segmentj is an older version, v0.1.14).

All that having been said, what can we surmise from these particular results?

  • segmentj performs better than stdlib at all encoding tasks.
  • jsoncolor performs better than segmentj for indentation (which makes sense, as indentation is performed inline).
  • jsoncolor performs better than stdlib at all encoding tasks.

Again, trust these benchmarks at your peril. Create your own benchmarks for your own workload.

Notes

  • The .golangci.yml linter settings have been fiddled with to hush some linting issues inherited from the segmentio codebase at the time of forking. Thus, the linter report may not be of great use. In an ideal world, the jsoncolor functionality would be ported to a more recent (and better-linted) version of the segementio codebase.
  • The segmentio encoder (at least as of v0.1.14) encodes time.Duration as string, while stdlib outputs as int64. This package follows stdlib.
  • The Colors.Punc field controls all punctuation colorization, i.e. []{},:". It is probably worthwhile to separate these out into individually-configurable elements.

CHANGELOG

History: this package is an extract of sq's JSON encoding package, which itself is a fork of the segmentio/encoding JSON encoding package. Note that the original sq JSON encoder was forked from Segment's codebase at v0.1.14, so the codebases have drifted significantly by now.

v0.7.1
  • #27: Improved Windows terminal color support checking.
v0.7.0

Acknowledgments

  • jq: sine qua non.
  • segmentio/encoding: jsoncolor is layered into Segment's JSON encoder. They did the hard work. Much gratitude to that team.
  • sq: jsoncolor is effectively an extract of code created specifically for sq.
  • mattn/go-colorable: no project is complete without mattn having played a role.
  • fatih/color: the color library.
  • @hermannm: for several PRs.

Documentation

Overview

Example (CustomMarshalJSON)
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"
)

type Animal int

const (
	Unknown Animal = iota
	Gopher
	Zebra
)

func (a *Animal) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	switch strings.ToLower(s) {
	default:
		*a = Unknown
	case "gopher":
		*a = Gopher
	case "zebra":
		*a = Zebra
	}

	return nil
}

func (a Animal) MarshalJSON() ([]byte, error) {
	var s string
	switch a {
	default:
		s = "unknown"
	case Gopher:
		s = "gopher"
	case Zebra:
		s = "zebra"
	}

	return json.Marshal(s)
}

func main() {
	blob := `["gopher","armadillo","zebra","unknown","gopher","bee","gopher","zebra"]`
	var zoo []Animal
	if err := json.Unmarshal([]byte(blob), &zoo); err != nil {
		log.Fatal(err)
	}

	census := make(map[Animal]int)
	for _, animal := range zoo {
		census[animal] += 1
	}

	fmt.Printf("Zoo Census:\n* Gophers: %d\n* Zebras:  %d\n* Unknown: %d\n",
		census[Gopher], census[Zebra], census[Unknown])

}
Output:

Zoo Census:
* Gophers: 3
* Zebras:  2
* Unknown: 3

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Append

func Append(b []byte, x interface{}, flags AppendFlags, clrs *Colors, indentr *indenter) ([]byte, error)

Append acts like Marshal but appends the json representation to b instead of always reallocating a new slice.

func Compact

func Compact(dst *bytes.Buffer, src []byte) error

Compact is documented at https://golang.org/pkg/encoding/json/#Compact

func HTMLEscape

func HTMLEscape(dst *bytes.Buffer, src []byte)

HTMLEscape is documented at https://golang.org/pkg/encoding/json/#HTMLEscape

Example
package main

import (
	"bytes"
	"encoding/json"
	"os"
)

func main() {
	var out bytes.Buffer
	json.HTMLEscape(&out, []byte(`{"Name":"<b>HTML content</b>"}`))
	out.WriteTo(os.Stdout)
}
Output:

{"Name":"\u003cb\u003eHTML content\u003c/b\u003e"}

func Indent

func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error

Indent is documented at https://golang.org/pkg/encoding/json/#Indent

Example
package main

import (
	"bytes"
	"encoding/json"
	"log"
	"os"
)

func main() {
	type Road struct {
		Name   string
		Number int
	}
	roads := []Road{
		{"Diamond Fork", 29},
		{"Sheep Creek", 51},
	}

	b, err := json.Marshal(roads)
	if err != nil {
		log.Fatal(err)
	}

	var out bytes.Buffer
	json.Indent(&out, b, "=", "\t")
	out.WriteTo(os.Stdout)
}
Output:

[
=	{
=		"Name": "Diamond Fork",
=		"Number": 29
=	},
=	{
=		"Name": "Sheep Creek",
=		"Number": 51
=	}
=]

func IsColorTerminal

func IsColorTerminal(w io.Writer) bool

IsColorTerminal returns true if w is a colorable terminal. It respects NO_COLOR, FORCE_COLOR and TERM=dumb environment variables.

func Marshal

func Marshal(x interface{}) ([]byte, error)

Marshal is documented at https://golang.org/pkg/encoding/json/#Marshal

Example
package main

import (
	"encoding/json"
	"fmt"
	"os"
)

func main() {
	type ColorGroup struct {
		ID     int
		Name   string
		Colors []string
	}
	group := ColorGroup{
		ID:     1,
		Name:   "Reds",
		Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
	}
	b, err := json.Marshal(group)
	if err != nil {
		fmt.Println("error:", err)
	}
	os.Stdout.Write(b)
}
Output:

{"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}

func MarshalIndent

func MarshalIndent(x interface{}, prefix, indent string) ([]byte, error)

MarshalIndent is documented at https://golang.org/pkg/encoding/json/#MarshalIndent

Example
package main

import (
	"encoding/json"
	"fmt"
	"log"
)

func main() {
	data := map[string]int{
		"a": 1,
		"b": 2,
	}

	json, err := json.MarshalIndent(data, "<prefix>", "<indent>")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(json))
}
Output:

{
<prefix><indent>"a": 1,
<prefix><indent>"b": 2
<prefix>}

func Parse

func Parse(b []byte, x interface{}, flags ParseFlags) ([]byte, error)

Parse behaves like Unmarshal but the caller can pass a set of flags to configure the parsing behavior.

func Unmarshal

func Unmarshal(b []byte, x interface{}) error

Unmarshal is documented at https://golang.org/pkg/encoding/json/#Unmarshal

Example
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var jsonBlob = []byte(`[
	{"Name": "Platypus", "Order": "Monotremata"},
	{"Name": "Quoll",    "Order": "Dasyuromorphia"}
]`)
	type Animal struct {
		Name  string
		Order string
	}
	var animals []Animal
	err := json.Unmarshal(jsonBlob, &animals)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%+v", animals)
}
Output:

[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]

func Valid

func Valid(data []byte) bool

Valid is documented at https://golang.org/pkg/encoding/json/#Valid

Example
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	goodJSON := `{"example": 1}`
	badJSON := `{"example":2:]}}`

	fmt.Println(json.Valid([]byte(goodJSON)), json.Valid([]byte(badJSON)))
}
Output:

true false

Types

type AppendFlags

type AppendFlags int

AppendFlags is a type used to represent configuration options that can be applied when formatting json output.

const (
	// EscapeHTML is a formatting flag used to to escape HTML in json strings.
	EscapeHTML AppendFlags = 1 << iota

	// SortMapKeys is formatting flag used to enable sorting of map keys when
	// encoding JSON (this matches the behavior of the standard encoding/json
	// package).
	SortMapKeys

	// TrustRawMessage is a performance optimization flag to skip value
	// checking of raw messages. It should only be used if the values are
	// known to be valid json (e.g., they were created by json.Unmarshal).
	TrustRawMessage
)

type Color

type Color []byte

Color is used to render terminal colors. In effect, Color is the bytes of the ANSI prefix code. The zero value is valid (results in no colorization). When Color is non-zero, the encoder writes the prefix, then the actual value, then the ANSI reset code.

Example value:

number := Color("\x1b[36m")

type Colors

type Colors struct {
	// Null is the color for JSON nil.
	Null Color

	// Bool is the color for boolean values.
	Bool Color

	// Number is the color for number values.
	Number Color

	// String is the color for string values.
	String Color

	// Key is the color for JSON keys.
	Key Color

	// Bytes is the color for byte data.
	Bytes Color

	// Time is the color for datetime values.
	Time Color

	// Punc is the color for JSON punctuation: []{},: etc.
	Punc Color

	// TextMarshaler is the color for values implementing encoding.TextMarshaler.
	TextMarshaler Color
}

Colors specifies colorization of JSON output. Each field is a Color, which is simply the bytes of the terminal color code.

func DefaultColors

func DefaultColors() *Colors

DefaultColors returns the default Colors configuration. These colors largely follow jq's default colorization, with some deviation.

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder is documented at https://golang.org/pkg/encoding/json/#Decoder

Example

This example uses a Decoder to decode a stream of distinct JSON values.

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"strings"
)

func main() {
	const jsonStream = `
	{"Name": "Ed", "Text": "Knock knock."}
	{"Name": "Sam", "Text": "Who's there?"}
	{"Name": "Ed", "Text": "Go fmt."}
	{"Name": "Sam", "Text": "Go fmt who?"}
	{"Name": "Ed", "Text": "Go fmt yourself!"}
`
	type Message struct {
		Name, Text string
	}
	dec := json.NewDecoder(strings.NewReader(jsonStream))
	for {
		var m Message
		if err := dec.Decode(&m); err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%s: %s\n", m.Name, m.Text)
	}
}
Output:

Ed: Knock knock.
Sam: Who's there?
Ed: Go fmt.
Sam: Go fmt who?
Ed: Go fmt yourself!

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder is documented at https://golang.org/pkg/encoding/json/#NewDecoder

func (*Decoder) Buffered

func (dec *Decoder) Buffered() io.Reader

Buffered is documented at https://golang.org/pkg/encoding/json/#Decoder.Buffered

func (*Decoder) Decode

func (dec *Decoder) Decode(v interface{}) error

Decode is documented at https://golang.org/pkg/encoding/json/#Decoder.Decode

Example (Stream)

This example uses a Decoder to decode a streaming array of JSON objects.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"
)

func main() {
	const jsonStream = `
	[
		{"Name": "Ed", "Text": "Knock knock."},
		{"Name": "Sam", "Text": "Who's there?"},
		{"Name": "Ed", "Text": "Go fmt."},
		{"Name": "Sam", "Text": "Go fmt who?"},
		{"Name": "Ed", "Text": "Go fmt yourself!"}
	]
`
	type Message struct {
		Name, Text string
	}
	dec := json.NewDecoder(strings.NewReader(jsonStream))

	// read open bracket
	t, err := dec.Token()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%T: %v\n", t, t)

	// while the array contains values
	for dec.More() {
		var m Message
		// decode an array value (Message)
		err := dec.Decode(&m)
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("%v: %v\n", m.Name, m.Text)
	}

	// read closing bracket
	t, err = dec.Token()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%T: %v\n", t, t)

}
Output:

json.Delim: [
Ed: Knock knock.
Sam: Who's there?
Ed: Go fmt.
Sam: Go fmt who?
Ed: Go fmt yourself!
json.Delim: ]

func (*Decoder) DisallowUnknownFields

func (dec *Decoder) DisallowUnknownFields()

DisallowUnknownFields is documented at https://golang.org/pkg/encoding/json/#Decoder.DisallowUnknownFields

func (*Decoder) DontCopyNumber

func (dec *Decoder) DontCopyNumber()

DontCopyNumber is an extension to the standard encoding/json package which instructs the decoder to not copy numbers loaded from the json payloads.

func (*Decoder) DontCopyRawMessage

func (dec *Decoder) DontCopyRawMessage()

DontCopyRawMessage is an extension to the standard encoding/json package which instructs the decoder to not allocate RawMessage values in separate memory buffers (see the documentation of the DontcopyRawMessage flag for more detais).

func (*Decoder) DontCopyString

func (dec *Decoder) DontCopyString()

DontCopyString is an extension to the standard encoding/json package which instructs the decoder to not copy strings loaded from the json payloads when possible.

func (*Decoder) DontMatchCaseInsensitiveStructFields

func (dec *Decoder) DontMatchCaseInsensitiveStructFields()

DontMatchCaseInsensitiveStructFields is an extension to the standard encoding/json package which instructs the decoder to not match object fields against struct fields in a case-insensitive way, the field names have to match exactly to be decoded into the struct field values.

func (*Decoder) InputOffset

func (dec *Decoder) InputOffset() int64

InputOffset returns the input stream byte offset of the current decoder position. The offset gives the location of the end of the most recently returned token and the beginning of the next token.

func (*Decoder) UseNumber

func (dec *Decoder) UseNumber()

UseNumber is documented at https://golang.org/pkg/encoding/json/#Decoder.UseNumber

func (*Decoder) ZeroCopy

func (dec *Decoder) ZeroCopy()

ZeroCopy is an extension to the standard encoding/json package which enables all the copy optimizations of the decoder.

type Delim

type Delim = json.Delim

Delim is documented at https://golang.org/pkg/encoding/json/#Delim

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder is documented at https://golang.org/pkg/encoding/json/#Encoder

Example

ExampleEncoder shows use of neilotoole/jsoncolor Encoder.

var enc *json.Encoder

// Note: this check will fail if running inside Goland (and
// other IDEs?) as IsColorTerminal will return false.
if json.IsColorTerminal(os.Stdout) {
	// Safe to use color
	out := colorable.NewColorable(os.Stdout) // needed for Windows
	enc = json.NewEncoder(out)

	// DefaultColors are similar to jq
	clrs := json.DefaultColors()

	// Change some values, just for fun
	clrs.Bool = json.Color("\x1b[36m") // Change the bool color
	clrs.String = json.Color{}         // Disable the string color

	enc.SetColors(clrs)
} else {
	// Can't use color; but the encoder will still work
	enc = json.NewEncoder(os.Stdout)
}

m := map[string]interface{}{
	"a": 1,
	"b": true,
	"c": "hello",
}

if err := enc.Encode(m); err != nil {
	fmt.Fprintln(os.Stderr, err)
}
Output:

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder is documented at https://golang.org/pkg/encoding/json/#NewEncoder

func (*Encoder) Encode

func (enc *Encoder) Encode(v interface{}) error

Encode is documented at https://golang.org/pkg/encoding/json/#Encoder.Encode

func (*Encoder) SetColors

func (enc *Encoder) SetColors(c *Colors)

SetColors sets the colors for the encoder to use.

func (*Encoder) SetEscapeHTML

func (enc *Encoder) SetEscapeHTML(on bool)

SetEscapeHTML is documented at https://golang.org/pkg/encoding/json/#Encoder.SetEscapeHTML

func (*Encoder) SetIndent

func (enc *Encoder) SetIndent(prefix, indent string)

SetIndent is documented at https://golang.org/pkg/encoding/json/#Encoder.SetIndent

func (*Encoder) SetSortMapKeys

func (enc *Encoder) SetSortMapKeys(on bool)

SetSortMapKeys is an extension to the standard encoding/json package which allows the program to toggle sorting of map keys on and off.

func (*Encoder) SetTrustRawMessage

func (enc *Encoder) SetTrustRawMessage(on bool)

SetTrustRawMessage skips value checking when encoding a raw json message. It should only be used if the values are known to be valid json, e.g. because they were originally created by json.Unmarshal.

type InvalidUTF8Error

type InvalidUTF8Error = json.InvalidUTF8Error

InvalidUTF8Error is documented at https://golang.org/pkg/encoding/json/#InvalidUTF8Error

type InvalidUnmarshalError

type InvalidUnmarshalError = json.InvalidUnmarshalError

InvalidUnmarshalError is documented at https://golang.org/pkg/encoding/json/#InvalidUnmarshalError

type Marshaler

type Marshaler = json.Marshaler

Marshaler is documented at https://golang.org/pkg/encoding/json/#Marshaler

type MarshalerError

type MarshalerError = json.MarshalerError

MarshalerError is documented at https://golang.org/pkg/encoding/json/#MarshalerError

type Number

type Number = json.Number

Number is documented at https://golang.org/pkg/encoding/json/#Number

type ParseFlags

type ParseFlags int

ParseFlags is a type used to represent configuration options that can be applied when parsing json input.

const (
	// DisallowUnknownFields is a parsing flag used to prevent decoding of
	// objects to Go struct values when a field of the input does not match
	// with any of the struct fields.
	DisallowUnknownFields ParseFlags = 1 << iota

	// UseNumber is a parsing flag used to load numeric values as Number
	// instead of float64.
	UseNumber

	// DontCopyString is a parsing flag used to provide zero-copy support when
	// loading string values from a json payload. It is not always possible to
	// avoid dynamic memory allocations, for example when a string is escaped in
	// the json data a new buffer has to be allocated, but when the `wire` value
	// can be used as content of a Go value the decoder will simply point into
	// the input buffer.
	DontCopyString

	// DontCopyNumber is a parsing flag used to provide zero-copy support when
	// loading Number values (see DontCopyString and DontCopyRawMessage).
	DontCopyNumber

	// DontCopyRawMessage is a parsing flag used to provide zero-copy support
	// when loading RawMessage values from a json payload. When used, the
	// RawMessage values will not be allocated into new memory buffers and
	// will instead point directly to the area of the input buffer where the
	// value was found.
	DontCopyRawMessage

	// DontMatchCaseInsensitiveStructFields is a parsing flag used to prevent
	// matching fields in a case-insensitive way. This can prevent degrading
	// performance on case conversions, and can also act as a stricter decoding
	// mode.
	DontMatchCaseInsensitiveStructFields

	// ZeroCopy is a parsing flag that combines all the copy optimizations
	// available in the package.
	//
	// The zero-copy optimizations are better used in request-handler style
	// code where none of the values are retained after the handler returns.
	ZeroCopy = DontCopyString | DontCopyNumber | DontCopyRawMessage
)

type RawMessage

type RawMessage = json.RawMessage

RawMessage is documented at https://golang.org/pkg/encoding/json/#RawMessage

Example (Marshal)

This example uses RawMessage to use a precomputed JSON during marshal.

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

func main() {
	h := json.RawMessage(`{"precomputed": true}`)

	c := struct {
		Header *json.RawMessage `json:"header"`
		Body   string           `json:"body"`
	}{Header: &h, Body: "Hello Gophers!"}

	b, err := json.MarshalIndent(&c, "", "\t")
	if err != nil {
		fmt.Println("error:", err)
	}
	os.Stdout.Write(b)

}
Output:

{
	"header": {
		"precomputed": true
	},
	"body": "Hello Gophers!"
}
Example (Unmarshal)

This example uses RawMessage to delay parsing part of a JSON message.

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

func main() {
	type Color struct {
		Space string
		Point json.RawMessage // delay parsing until we know the color space
	}
	type RGB struct {
		R uint8
		G uint8
		B uint8
	}
	type YCbCr struct {
		Y  uint8
		Cb int8
		Cr int8
	}

	var j = []byte(`[
	{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
	{"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255}}
]`)
	var colors []Color
	err := json.Unmarshal(j, &colors)
	if err != nil {
		log.Fatalln("error:", err)
	}

	for _, c := range colors {
		var dst interface{}
		switch c.Space {
		case "RGB":
			dst = new(RGB)
		case "YCbCr":
			dst = new(YCbCr)
		}
		err := json.Unmarshal(c.Point, dst)
		if err != nil {
			log.Fatalln("error:", err)
		}
		fmt.Println(c.Space, dst)
	}
}
Output:

YCbCr &{255 0 -10}
RGB &{98 218 255}

type RawValue

type RawValue []byte

RawValue represents a raw json value, it is intended to carry null, true, false, number, and string values only.

func (RawValue) AppendUnquote

func (v RawValue) AppendUnquote(b []byte) []byte

AppendUnquote writes the unquoted version of the string value in v into b.

func (RawValue) False

func (v RawValue) False() bool

False returns true if v contains a false value.

func (RawValue) Null

func (v RawValue) Null() bool

Null returns true if v contains a null value.

func (RawValue) Number

func (v RawValue) Number() bool

Number returns true if v contains a number value.

func (RawValue) String

func (v RawValue) String() bool

String returns true if v contains a string value.

func (RawValue) True

func (v RawValue) True() bool

True returns true if v contains a true value.

func (RawValue) Unquote

func (v RawValue) Unquote() []byte

Unquote returns the unquoted version of the string value in v.

type SyntaxError

type SyntaxError = json.SyntaxError

A SyntaxError is a description of a JSON syntax error.

type Token

type Token = json.Token

Token is documented at https://golang.org/pkg/encoding/json/#Token

type Tokenizer

type Tokenizer struct {
	// When the tokenizer is positioned on a json delimiter this field is not
	// zero. In this case the possible values are '{', '}', '[', ']', ':', and
	// ','.
	Delim Delim

	// This field contains the raw json token that the tokenizer is pointing at.
	// When Delim is not zero, this field is a single-element byte slice
	// continaing the delimiter value. Otherwise, this field holds values like
	// null, true, false, numbers, or quoted strings.
	Value RawValue

	// When the tokenizer has encountered invalid content this field is not nil.
	Err error

	// When the value is in an array or an object, this field contains the depth
	// at which it was found.
	Depth int

	// When the value is in an array or an object, this field contains the
	// position at which it was found.
	Index int

	// This field is true when the value is the key of an object.
	IsKey bool
	// contains filtered or unexported fields
}

Tokenizer is an iterator-style type which can be used to progressively parse through a json input.

Tokenizing json is useful to build highly efficient parsing operations, for example when doing tranformations on-the-fly where as the program reads the input and produces the transformed json to an output buffer.

Here is a common pattern to use a tokenizer:

for t := json.NewTokenizer(b); t.Next(); {
	switch t.Delim {
	case '{':
		...
	case '}':
		...
	case '[':
		...
	case ']':
		...
	case ':':
		...
	case ',':
		...
	}

	switch {
	case t.Value.String():
		...
	case t.Value.Null():
		...
	case t.Value.True():
		...
	case t.Value.False():
		...
	case t.Value.Number():
		...
	}
}

func NewTokenizer

func NewTokenizer(b []byte) *Tokenizer

NewTokenizer constructs a new Tokenizer which reads its json input from b.

func (*Tokenizer) Next

func (t *Tokenizer) Next() bool

Next returns a new tokenizer pointing at the next token, or the zero-value of Tokenizer if the end of the json input has been reached.

If the tokenizer encounters malformed json while reading the input the method sets t.Err to an error describing the issue, and returns false. Once an error has been encountered, the tokenizer will always fail until its input is cleared by a call to its Reset method.

func (*Tokenizer) Reset

func (t *Tokenizer) Reset(b []byte)

Reset erases the state of t and re-initializes it with the json input from b.

type UnmarshalFieldError

type UnmarshalFieldError = json.UnmarshalFieldError

UnmarshalFieldError is documented at https://golang.org/pkg/encoding/json/#UnmarshalFieldError

type UnmarshalTypeError

type UnmarshalTypeError = json.UnmarshalTypeError

UnmarshalTypeError is documented at https://golang.org/pkg/encoding/json/#UnmarshalTypeError

type Unmarshaler

type Unmarshaler = json.Unmarshaler

Unmarshaler is documented at https://golang.org/pkg/encoding/json/#Unmarshaler

type UnsupportedTypeError

type UnsupportedTypeError = json.UnsupportedTypeError

UnsupportedTypeError is documented at https://golang.org/pkg/encoding/json/#UnsupportedTypeError

type UnsupportedValueError

type UnsupportedValueError = json.UnsupportedValueError

UnsupportedValueError is documented at https://golang.org/pkg/encoding/json/#UnsupportedValueError

Directories

Path Synopsis
cmd
jc
helper
fatihcolor
Package fatihcolor provides an adapter between fatih/color and neilotoole/jsoncolor's native mechanism.
Package fatihcolor provides an adapter between fatih/color and neilotoole/jsoncolor's native mechanism.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL