{"id":13413261,"url":"https://github.com/wI2L/jettison","last_synced_at":"2025-03-14T19:31:48.294Z","repository":{"id":45297265,"uuid":"205387787","full_name":"wI2L/jettison","owner":"wI2L","description":"Highly configurable, fast JSON encoder for Go","archived":false,"fork":false,"pushed_at":"2023-07-28T09:54:40.000Z","size":961,"stargazers_count":173,"open_issues_count":2,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-15T00:27:44.343Z","etag":null,"topics":["encoder","go","golang","json","json-encoder","marshalling"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/wI2L/jettison","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wI2L.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-08-30T13:28:03.000Z","updated_at":"2024-09-26T07:38:31.000Z","dependencies_parsed_at":"2024-01-08T15:34:40.430Z","dependency_job_id":null,"html_url":"https://github.com/wI2L/jettison","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Fjettison","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Fjettison/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Fjettison/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wI2L%2Fjettison/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wI2L","download_url":"https://codeload.github.com/wI2L/jettison/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243635331,"owners_count":20322921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["encoder","go","golang","json","json-encoder","marshalling"],"created_at":"2024-07-30T20:01:36.343Z","updated_at":"2025-03-14T19:31:47.986Z","avatar_url":"https://github.com/wI2L.png","language":"Go","funding_links":[],"categories":["JSON","Relational Databases"],"sub_categories":["Search and Analytic Databases","Advanced Console UIs","检索及分析资料库","SQL 查询语句构建库"],"readme":"\u003ch1 align=\"center\"\u003eJettison\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\u003cimg src=\"images/logo.png\" height=\"275px\" width=\"auto\" alt=\"GoCaptain\"\u003e\u003c/p\u003e\u003cp align=\"center\"\u003eJettison is a fast and flexible \u003cstrong\u003eJSON\u003c/strong\u003e encoder for the Go programming language, inspired by \u003ca href=\"https://github.com/bet365/jingo\"\u003ebet365/jingo\u003c/a\u003e, with a richer features set, aiming at \u003cstrong\u003e100%\u003c/strong\u003e compatibility with the standard library.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/wI2L/jettison?tab=doc\"\u003e\u003cimg src=\"https://img.shields.io/static/v1?label=godev\u0026message=reference\u0026color=00add8\u0026logo=go\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/wI2L/jettison\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/wI2L/fizz\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://travis-ci.org/wI2L/jettison\"\u003e\u003cimg src=\"https://travis-ci.org/wI2L/jettison.svg?branch=master\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/wI2L/jettison/actions\"\u003e\u003cimg src=\"https://github.com/wI2L/jettison/workflows/CI/badge.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/wI2L/jettison\"\u003e\u003cimg src=\"https://codecov.io/gh/wI2L/jettison/branch/master/graph/badge.svg\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/wI2L/jettison/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/tag/wI2L/jettison?color=blueviolet\u0026label=version\u0026sort=semver\"\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/avelino/awesome-go\"\u003e\u003cimg src=\"https://awesome.re/mentioned-badge.svg\"\u003e\u003c/a\u003e\n\u003cbr\u003e\n\u003c/p\u003e\n\n---\n\n## Installation\n\nJettison uses [Go modules](https://github.com/golang/go/wiki/Modules). Releases are tagged according to the _SemVer_ format, prefixed with a `v`, starting from *0.2.0*. You can get the latest release using the following command.\n\n```console\n$ go get github.com/wI2L/jettison@latest\n```\n\n:warning: From version `v0.7.4`, the package requires [Go 1.17+](https://golang.org/doc/install) to build, due to the usage of the [new build constraints](https://go.googlesource.com/proposal/+/master/design/draft-gobuild.md).\n\n## Key features\n\n- Fast, see [benchmarks](#benchmarks)\n- No dynamic memory allocations in hot paths\n- Behavior identical to the standard library by default\n- No code generation required\n- Clear and concise API\n- Configurable with opt-in functional options\n- Native support for many standard library types, see [improvements](#improvements)\n- Custom `AppendMarshaler` interface to avoid allocations\n- Extensive testsuite that compares its output against `encoding/json`\n\n## Overview\n\nThe goal of Jettision is to take up the idea introduced by the **bet365/jingo** package and build a fully-featured JSON encoder around it, that comply with the behavior of the [encoding/json](https://golang.org/pkg/encoding/json/) package. Unlike the latter, Jettison does not use reflection during marshaling, but only once to create the instruction set for a given type ahead of time. The drawback to this approach requires to instantiate an instruction-set once for each type that needs to be marshaled, but that is overcomed with a package cache.\n\nThe package aims to have a behavior similar to that of the standard library for all types encoding and struct tags, meaning that the documentation of the `json.Marshal` [function](https://golang.org/pkg/encoding/json/#Marshal) is applicable for Jettison, with a few exceptions described in this [section](#differences-with-encodingjson). As such, most of the tests compare their output against it to guarantee that.\n\n### Implementation details\n\nThe main concept of Jettison consists of using pre-build instructions-set to reduce the cost of using the `reflect` package at runtime. When marshaling a value, a set of _instructions_ is recursively generated for its type, which defines how to iteratively encode it. An _instruction_ is a function or a closure, that have all the information required to read the data from memory using _unsafe_ operations (pointer type conversion, arithmetic...) during the instruction set execution.\n\n### Differences with `encoding/json`\n\nAll notable differences with the standard library behavior are listed below. Please note that these might evolve with future versions of the package.\n\n#### Improvements\n\n- The `time.Time` and `time.Duration` types are handled natively. For time values, the encoder doesn't invoke `MarshalJSON` or `MarshalText`, but use the `time.AppendFormat` [function](https://golang.org/pkg/time/#Time.AppendFormat) instead, and write the result to the stream. Similarly, for durations, it isn't necessary to implements the `json.Marshaler` or `encoding.TextMarshaler` interfaces on a custom wrapper type, the encoder uses the result of one of the methods `Minutes`, `Seconds`, `Nanoseconds` or `String`, based on the duration [format](https://godoc.org/github.com/wI2L/jettison#DurationFmt) configured.\n\n- The `sync.Map` type is handled natively. The marshaling behavior is similar to the one of a standard Go `map`. The option `UnsortedMap` can also be used in cunjunction with this type to disable the default keys sort.\n\n- The `omitnil` field tag's option can be used to specify that a field with a nil pointer should be omitted from the encoding. This option has precedence over the `omitempty` option. Note that struct fields that implement the `json.Marshaler` interface will be omitted too, if they return the literal JSON `null` value.\n\n#### Bugs\n\n##### Go1.13 and backward\n\n- Nil map keys values implementing the `encoding.TextMarshaler` interface are encoded as empty strings, while the `encoding/json` package currently panic because of that. See this [issue](https://github.com/golang/go/issues/33675) for more details.\u003csup\u003e[1]\u003c/sup\u003e\n\n- Nil struct fields implementing the `encoding.TextMarshaler` interface are encoded as `null`, while the `encoding/json` package currently panic because of that. See this [issue](https://github.com/golang/go/issues/34235) for more details.\u003csup\u003e[1]\u003c/sup\u003e\n\n\u003csup\u003e1: The issues mentioned above have had their associated CL merged, and was released with Go 1.14.\u003c/sup\u003e\n\n## Usage\n\n### Basic\n\nAs stated above, the library behave similarly to the `encoding/json` package. You can simply replace the `json.Marshal` function with `jettison.Marshal`, and expect the same output with better performances.\n\n```go\ntype X struct {\n   A string `json:\"a\"`\n   B int64  `json:\"b\"`\n}\nb, err := jettison.Marshal(X{\n   A: \"Loreum\",\n   B: 42,\n})\nif err != nil {\n   log.Fatal(err)\n}\nos.Stdout.Write(b)\n```\n###### Result\n```json\n{\"a\":\"Loreum\",\"b\":42}\n```\n\n### Advanced\n\nIf more control over the encoding behavior is required, use the `MarshalOpts` function instead. The second parameter is variadic and accept a list of functional opt-in [options](https://godoc.org/github.com/wI2L/jettison#Option) described below:\n\n|           name           | description                                                                                                                                                                        |\n|:------------------------:| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|     **`TimeLayout`**     | Defines the layout used to encode `time.Time` values. The layout must be compatible with the [AppendFormat](https://golang.org/pkg/time/#Time.AppendFormat) method.                |\n|   **`DurationFormat`**   | Defines the format used to encode `time.Duration` values. See the documentation of the `DurationFmt` type for the complete list of formats available.                              |\n|      **`UnixTime`**      | Encode `time.Time` values as JSON numbers representing Unix timestamps, the number of seconds elapsed since *January 1, 1970 UTC*. This option has precedence over `TimeLayout`.   |\n|    **`UnsortedMap`**     | Disables map keys sort.                                                                                                                                                            |\n| **`ByteArrayAsString`**  | Encodes byte arrays as JSON strings rather than JSON arrays. The output is subject to the same escaping rules used for JSON strings, unless the option `NoStringEscaping` is used. |\n|    **`RawByteSlice`**    | Disables the *base64* default encoding used for byte slices.                                                                                                                       |\n|    **`NilMapEmpty`**     | Encodes nil Go maps as empty JSON objects rather than `null`.                                                                                                                      |\n|   **`NilSliceEmpty`**    | Encodes nil Go slices as empty JSON arrays rather than `null`.                                                                                                                     |\n|  **`NoStringEscaping`**  | Disables string escaping. `NoHTMLEscaping` and `NoUTF8Coercion` are ignored when this option is used.                                                                              |\n|   **`NoHTMLEscaping`**   | Disables the escaping of special HTML characters such as `\u0026`, `\u003c` and `\u003e` in JSON strings. This is similar to `json.Encoder.SetEscapeHTML(false)`.                                 |\n|   **`NoUTF8Coercion`**   | Disables the replacement of invalid bytes with the Unicode replacement rune in JSON strings.                                                                                       |\n|     **`AllowList`**      | Sets a whitelist that represents which fields are to be encoded when marshaling a Go struct.                                                                                       |\n|      **`DenyList`**      | Sets a blacklist that represents which fields are ignored during the marshaling of a Go struct.                                                                                    |\n|     **`NoCompact`**      | Disables the compaction of JSON output produced by `MarshalJSON` method, and `json.RawMessage` values.                                                                             |\n| **`NoNumberValidation`** | Disables the validation of `json.Number` values.                                                                                                                                   |\n|    **`WithContext`**     | Sets the `context.Context` to be passed to invocations of `AppendJSONContext` methods.                                                                                             |\n\nTake a look at the [examples](example_test.go) to see these options in action.\n\n## Benchmarks\n\nIf you'd like to run the benchmarks yourself, use the following command.\n\n```shell\ngo get github.com/cespare/prettybench\ngo test -bench=. | prettybench\n```\n\n### Results `-short`\n\nThese benchmarks were run 10x (statistics computed with [benchstat](https://godoc.org/golang.org/x/perf/cmd/benchstat)) on a MacBook Pro 15\", with the following specs:\n```\nOS:  macOS Catalina (10.15.7)\nCPU: 2.6 GHz Intel Core i7\nMem: 16GB\nGo:  go version go1.17 darwin/amd64\nTag: v0.7.2\n```\n\n\u003cdetails\u003e\u003csummary\u003eStats\u003c/summary\u003e\u003cbr\u003e\u003cpre\u003e\nname                    time/op\nSimple/standard-8          573ns ± 1%\nSimple/jsoniter-8          547ns ± 0%\nSimple/segmentj-8          262ns ± 1%\nSimple/jettison-8          408ns ± 1%\nComplex/standard-8        11.7µs ± 0%\nComplex/jsoniter-8        11.6µs ± 1%\nComplex/segmentj-8        7.96µs ± 0%\nComplex/jettison-8        5.90µs ± 1%\nCodeMarshal/standard-8    6.71ms ± 0%\nCodeMarshal/jsoniter-8    6.35ms ± 1%\nCodeMarshal/segmentj-8    4.38ms ± 1%\nCodeMarshal/jettison-8    5.56ms ± 1%\nMap/standard-8            1.83µs ± 1%\nMap/jsoniter-8            1.65µs ± 0%\nMap/segmentj-8            1.61µs ± 0%\nMap/jettison-8             772ns ± 1%\nMap/jettison-nosort-8      507ns ± 1%\n\nname                    speed\nSimple/standard-8        236MB/s ± 1%\nSimple/jsoniter-8        247MB/s ± 0%\nSimple/segmentj-8        516MB/s ± 1%\nSimple/jettison-8        331MB/s ± 1%\nComplex/standard-8      72.9MB/s ± 0%\nComplex/jsoniter-8      70.6MB/s ± 0%\nComplex/segmentj-8       108MB/s ± 0%\nComplex/jettison-8       144MB/s ± 1%\nCodeMarshal/standard-8   289MB/s ± 0%\nCodeMarshal/jsoniter-8   306MB/s ± 1%\nCodeMarshal/segmentj-8   443MB/s ± 1%\nCodeMarshal/jettison-8   349MB/s ± 1%\nMap/standard-8          46.6MB/s ± 1%\nMap/jsoniter-8          51.5MB/s ± 0%\nMap/segmentj-8          52.8MB/s ± 0%\nMap/jettison-8           110MB/s ± 1%\nMap/jettison-nosort-8    168MB/s ± 1%\n\nname                    alloc/op\nSimple/standard-8           144B ± 0%\nSimple/jsoniter-8           152B ± 0%\nSimple/segmentj-8           144B ± 0%\nSimple/jettison-8           144B ± 0%\nComplex/standard-8        4.05kB ± 0%\nComplex/jsoniter-8        3.95kB ± 0%\nComplex/segmentj-8        2.56kB ± 0%\nComplex/jettison-8          935B ± 0%\nCodeMarshal/standard-8    1.97MB ± 0%\nCodeMarshal/jsoniter-8    2.00MB ± 0%\nCodeMarshal/segmentj-8    1.98MB ± 2%\nCodeMarshal/jettison-8    1.98MB ± 2%\nMap/standard-8              888B ± 0%\nMap/jsoniter-8              884B ± 0%\nMap/segmentj-8              576B ± 0%\nMap/jettison-8             96.0B ± 0%\nMap/jettison-nosort-8       160B ± 0%\n\nname                    allocs/op\nSimple/standard-8           1.00 ± 0%\nSimple/jsoniter-8           2.00 ± 0%\nSimple/segmentj-8           1.00 ± 0%\nSimple/jettison-8           1.00 ± 0%\nComplex/standard-8          79.0 ± 0%\nComplex/jsoniter-8          71.0 ± 0%\nComplex/segmentj-8          52.0 ± 0%\nComplex/jettison-8          8.00 ± 0%\nCodeMarshal/standard-8      1.00 ± 0%\nCodeMarshal/jsoniter-8      2.00 ± 0%\nCodeMarshal/segmentj-8      1.00 ± 0%\nCodeMarshal/jettison-8      1.00 ± 0%\nMap/standard-8              19.0 ± 0%\nMap/jsoniter-8              14.0 ± 0%\nMap/segmentj-8              18.0 ± 0%\nMap/jettison-8              1.00 ± 0%\nMap/jettison-nosort-8       2.00 ± 0%\n\u003c/pre\u003e\u003c/details\u003e\n\n#### Simple [[source](https://github.com/wI2L/jettison/blob/master/bench_test.go#L50)]\n\nBasic payload with fields of type `string`, `int` and `bool`.\n\n![Simple Benchmark Graph](./images/benchmarks/simple.svg)\n\n#### Complex [[source](https://github.com/wI2L/jettison/blob/master/bench_test.go#L65)]\n\nLarge payload with a variety of composite Go types, such as `struct`, `map`, `interface`, multi-dimensions `array` and `slice`, with pointer and non-pointer value types.\n\nPlease note that this test is somewhat positively influenced by the performances of map marshaling.\n\n![Complex Benchmark Graph](./images/benchmarks/complex.svg)\n\n#### CodeMarshal [[source](https://github.com/wI2L/jettison/blob/master/bench_test.go#L69)]\n\nBorrowed from the `encoding/json` tests. See [testdata/code.json.gz](testdata/code.json.gz).\n\n![CodeMarshal Benchmark Graph](./images/benchmarks/code-marshal.svg)\n\n#### Map [[source](https://github.com/wI2L/jettison/blob/master/bench_test.go#L75)]\n\nSimple `map[string]int` with 6 keys.\n\n![Map Graph](./images/benchmarks/map.svg)\n\n## Credits\n\nThis library and its design has been inspired by the work of others at **@bet365** and **@segmentio**.\nSee the following projects for reference:\n- [bet365/jingo](https://github.com/bet365/jingo)\n- [segmentio/encoding](https://github.com/segmentio/encoding)\n\n## License\n\nJettison is licensed under the **MIT** license. See the [LICENSE](LICENSE) file.\n\nThis package also uses some portions of code from the Go **encoding/json** package. The associated license can be found in [LICENSE.golang](LICENSE.golang).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FwI2L%2Fjettison","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FwI2L%2Fjettison","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FwI2L%2Fjettison/lists"}