From a57b12847a060ed277ca43703da2ddb23a710ba8 Mon Sep 17 00:00:00 2001
From: re
-
+
set a json value quickly
SJSON is a Go package that provides a [very fast](#performance) and simple way to set a value in a json document. -For quickly retrieving json values check out [GJSON](https://github.com/tidwall/gjson). +For quickly retrieving json values check out [GJSON](https://git.internal/re/gjson). For a command line interface check out [JJ](https://github.com/tidwall/jj). @@ -22,7 +22,7 @@ Installing To start using SJSON, install Go and run `go get`: ```sh -$ go get -u github.com/tidwall/sjson +$ go get -u git.internal/re/sjson ``` This will retrieve the library. @@ -38,7 +38,7 @@ Invalid paths may return an error. ```go package main -import "github.com/tidwall/sjson" +import "git.internal/re/sjson" const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}` @@ -268,7 +268,7 @@ widget.image.hOffset widget.text.onMouseUp ``` -*These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.7 and can be be found [here](https://github.com/tidwall/sjson-benchmarks)*. +*These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.7 and can be be found [here](https://git.internal/re/sjson-benchmarks)*. ## Contact Josh Baker [@tidwall](http://twitter.com/tidwall) diff --git a/go.mod b/go.mod index fa6b7e8..b08754e 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ -module github.com/tidwall/sjson +module git.internal/re/sjson go 1.14 require ( - github.com/tidwall/gjson v1.14.2 + git.internal/re/gjson v1.14.4 github.com/tidwall/pretty v1.2.0 ) diff --git a/go.sum b/go.sum index ec6ee0a..6b4fa66 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo= -github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +git.internal/re/gjson v1.14.4 h1:h247IjFbi0EbPbaP9uhmjF4d4BBZdzp3IqVdPbOfNlQ= +git.internal/re/gjson v1.14.4/go.mod h1:nWhPHhrw7k8ssdzMTMcw6ButkZOJV9xeqauMiGbDEmo= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= diff --git a/sjson.go b/sjson.go index a55eef3..6623905 100644 --- a/sjson.go +++ b/sjson.go @@ -7,7 +7,7 @@ import ( "strconv" "unsafe" - "github.com/tidwall/gjson" + "git.internal/re/gjson" ) type errorType struct { @@ -134,7 +134,8 @@ func appendStringify(buf []byte, s string) []byte { // appendBuild builds a json block from a json path. func appendBuild(buf []byte, array bool, paths []pathResult, raw string, - stringify bool) []byte { + stringify bool, +) []byte { if !array { buf = appendStringify(buf, paths[0].part) buf = append(buf, ':') @@ -248,7 +249,8 @@ loop: var errNoChange = &errorType{"no change"} func appendRawPaths(buf []byte, jstr string, paths []pathResult, raw string, - stringify, del bool) ([]byte, error) { + stringify, del bool, +) ([]byte, error) { var err error var res gjson.Result var found bool @@ -365,7 +367,8 @@ func appendRawPaths(buf []byte, jstr string, paths []pathResult, raw string, } else { return nil, &errorType{ "cannot set array element for non-numeric key '" + - paths[0].part + "'"} + paths[0].part + "'", + } } } if appendit { @@ -427,19 +430,18 @@ func isOptimisticPath(path string) bool { // // A path is a series of keys separated by a dot. // -// { -// "name": {"first": "Tom", "last": "Anderson"}, -// "age":37, -// "children": ["Sara","Alex","Jack"], -// "friends": [ -// {"first": "James", "last": "Murphy"}, -// {"first": "Roger", "last": "Craig"} -// ] -// } -// "name.last" >> "Anderson" -// "age" >> 37 -// "children.1" >> "Alex" -// +// { +// "name": {"first": "Tom", "last": "Anderson"}, +// "age":37, +// "children": ["Sara","Alex","Jack"], +// "friends": [ +// {"first": "James", "last": "Murphy"}, +// {"first": "Roger", "last": "Craig"} +// ] +// } +// "name.last" >> "Anderson" +// "age" >> 37 +// "children.1" >> "Alex" func Set(json, path string, value interface{}) (string, error) { return SetOptions(json, path, value, nil) } @@ -504,7 +506,8 @@ type sliceHeader struct { } func set(jstr, path, raw string, - stringify, del, optimistic, inplace bool) ([]byte, error) { + stringify, del, optimistic, inplace bool, +) ([]byte, error) { if path == "" { return []byte(jstr), &errorType{"path cannot be empty"} } @@ -519,7 +522,8 @@ func set(jstr, path, raw string, if !stringify || !mustMarshalString(raw) { jsonh := *(*stringHeader)(unsafe.Pointer(&jstr)) jsonbh := sliceHeader{ - data: jsonh.data, len: jsonh.len, cap: jsonh.len} + data: jsonh.data, len: jsonh.len, cap: jsonh.len, + } jbytes := *(*[]byte)(unsafe.Pointer(&jsonbh)) if stringify { jbytes[res.Index] = '"' @@ -629,7 +633,8 @@ func setComplexPath(jstr, path, raw string, stringify bool) ([]byte, error) { // Invalid json will not panic, but it may return back unexpected results. // An error is returned if the path is not valid. func SetOptions(json, path string, value interface{}, - opts *Options) (string, error) { + opts *Options, +) (string, error) { if opts != nil { if opts.ReplaceInPlace { // it's not safe to replace bytes in-place for strings @@ -650,7 +655,8 @@ func SetOptions(json, path string, value interface{}, // If working with bytes, this method preferred over // SetOptions(string(data), path, value) func SetBytesOptions(json []byte, path string, value interface{}, - opts *Options) ([]byte, error) { + opts *Options, +) ([]byte, error) { var optimistic, inplace bool if opts != nil { optimistic = opts.Optimistic @@ -721,7 +727,8 @@ func SetBytesOptions(json []byte, path string, value interface{}, // If working with bytes, this method preferred over // SetRawOptions(string(data), path, value, opts) func SetRawBytesOptions(json []byte, path string, value []byte, - opts *Options) ([]byte, error) { + opts *Options, +) ([]byte, error) { jstr := *(*string)(unsafe.Pointer(&json)) vstr := *(*string)(unsafe.Pointer(&value)) var optimistic, inplace bool diff --git a/sjson_test.go b/sjson_test.go index aa3d968..44fd2cd 100644 --- a/sjson_test.go +++ b/sjson_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/tidwall/gjson" + "git.internal/re/gjson" "github.com/tidwall/pretty" ) @@ -62,6 +62,7 @@ func testRaw(t *testing.T, kind int, expect, json, path string, value interface{ t.Fatalf("expected '%v', got '%v'", expect, string(json3)) } } + func TestBasic(t *testing.T) { testRaw(t, setRaw, `[{"hiw":"planet","hi":"world"}]`, `[{"hi":"world"}]`, "0.hiw", `"planet"`) testRaw(t, setRaw, `[true]`, ``, "0", `true`) @@ -190,7 +191,7 @@ func TestDeleteIssue21(t *testing.T) { expectedForLenBefore309AsBytes := `{"1":"","0":"01234567890123456789012345678901234567890123456789012345678901234567890123456","2":""}` //--------------------------- - var data = []struct { + data := []struct { desc string input string expected string @@ -214,7 +215,6 @@ func TestDeleteIssue21(t *testing.T) { for i, d := range data { result, err := Delete(d.input, "to_delete") - if err != nil { t.Error(fmtErrorf(testError{ unexpected: "error", @@ -270,6 +270,7 @@ func TestSetDotKeyIssue10(t *testing.T) { t.Fatalf("expected '%v', got '%v'", `{"app.token":"cde"}`, json) } } + func TestDeleteDotKeyIssue19(t *testing.T) { json := []byte(`{"data":{"key1":"value1","key2.something":"value2"}}`) json, _ = DeleteBytes(json, `data.key2\.something`) @@ -279,12 +280,12 @@ func TestDeleteDotKeyIssue19(t *testing.T) { } func TestIssue36(t *testing.T) { - var json = ` + json := ` { "size": 1000 } ` - var raw = ` + raw := ` { "sample": "hello" }