GithubHelp home page GithubHelp logo

sjson's Introduction

SJSON
GoDoc

set a json value quickly

SJSON is a Go package that provides a very fast and simple way to set a value in a json document. For quickly retrieving json values check out GJSON.

For a command line interface check out JJ.

Getting Started

Installing

To start using SJSON, install Go and run go get:

$ go get -u github.com/tidwall/sjson

This will retrieve the library.

Set a value

Set sets the value for the specified path. A path is in dot syntax, such as "name.last" or "age". This function expects that the json is well-formed and validated. Invalid json will not panic, but it may return back unexpected results. Invalid paths may return an error.

package main

import "github.com/tidwall/sjson"

const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`

func main() {
	value, _ := sjson.Set(json, "name.last", "Anderson")
	println(value)
}

This will print:

{"name":{"first":"Janet","last":"Anderson"},"age":47}

Path syntax

A path is a series of keys separated by a dot. The dot and colon characters can be escaped with \.

{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
	{"first": "James", "last": "Murphy"},
	{"first": "Roger", "last": "Craig"}
  ]
}
"name.last"          >> "Anderson"
"age"                >> 37
"children.1"         >> "Alex"
"friends.1.last"     >> "Craig"

The -1 key can be used to append a value to an existing array:

"children.-1"  >> appends a new value to the end of the children array

Normally number keys are used to modify arrays, but it's possible to force a numeric object key by using the colon character:

{
  "users":{
    "2313":{"name":"Sara"},
    "7839":{"name":"Andy"}
  }
}

A colon path would look like:

"users.:2313.name"    >> "Sara"

Supported types

Pretty much any type is supported:

sjson.Set(`{"key":true}`, "key", nil)
sjson.Set(`{"key":true}`, "key", false)
sjson.Set(`{"key":true}`, "key", 1)
sjson.Set(`{"key":true}`, "key", 10.5)
sjson.Set(`{"key":true}`, "key", "hello")
sjson.Set(`{"key":true}`, "key", []string{"hello", "world"})
sjson.Set(`{"key":true}`, "key", map[string]interface{}{"hello":"world"})

When a type is not recognized, SJSON will fallback to the encoding/json Marshaller.

Examples

Set a value from empty document:

value, _ := sjson.Set("", "name", "Tom")
println(value)

// Output:
// {"name":"Tom"}

Set a nested value from empty document:

value, _ := sjson.Set("", "name.last", "Anderson")
println(value)

// Output:
// {"name":{"last":"Anderson"}}

Set a new value:

value, _ := sjson.Set(`{"name":{"last":"Anderson"}}`, "name.first", "Sara")
println(value)

// Output:
// {"name":{"first":"Sara","last":"Anderson"}}

Update an existing value:

value, _ := sjson.Set(`{"name":{"last":"Anderson"}}`, "name.last", "Smith")
println(value)

// Output:
// {"name":{"last":"Smith"}}

Set a new array value:

value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.2", "Sara")
println(value)

// Output:
// {"friends":["Andy","Carol","Sara"]

Append an array value by using the -1 key in a path:

value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.-1", "Sara")
println(value)

// Output:
// {"friends":["Andy","Carol","Sara"]

Append an array value that is past the end:

value, _ := sjson.Set(`{"friends":["Andy","Carol"]}`, "friends.4", "Sara")
println(value)

// Output:
// {"friends":["Andy","Carol",null,null,"Sara"]

Delete a value:

value, _ := sjson.Delete(`{"name":{"first":"Sara","last":"Anderson"}}`, "name.first")
println(value)

// Output:
// {"name":{"last":"Anderson"}}

Delete an array value:

value, _ := sjson.Delete(`{"friends":["Andy","Carol"]}`, "friends.1")
println(value)

// Output:
// {"friends":["Andy"]}

Delete the last array value:

value, _ := sjson.Delete(`{"friends":["Andy","Carol"]}`, "friends.-1")
println(value)

// Output:
// {"friends":["Andy"]}

Performance

Benchmarks of SJSON alongside encoding/json, ffjson, EasyJSON, and Gabs

Benchmark_SJSON-8                  	 3000000	       805 ns/op	    1077 B/op	       3 allocs/op
Benchmark_SJSON_ReplaceInPlace-8   	 3000000	       449 ns/op	       0 B/op	       0 allocs/op
Benchmark_JSON_Map-8               	  300000	     21236 ns/op	    6392 B/op	     150 allocs/op
Benchmark_JSON_Struct-8            	  300000	     14691 ns/op	    1789 B/op	      24 allocs/op
Benchmark_Gabs-8                   	  300000	     21311 ns/op	    6752 B/op	     150 allocs/op
Benchmark_FFJSON-8                 	  300000	     17673 ns/op	    3589 B/op	      47 allocs/op
Benchmark_EasyJSON-8               	 1500000	      3119 ns/op	    1061 B/op	      13 allocs/op

JSON document used:

{
  "widget": {
    "debug": "on",
    "window": {
      "title": "Sample Konfabulator Widget",
      "name": "main_window",
      "width": 500,
      "height": 500
    },
    "image": { 
      "src": "Images/Sun.png",
      "hOffset": 250,
      "vOffset": 250,
      "alignment": "center"
    },
    "text": {
      "data": "Click Here",
      "size": 36,
      "style": "bold",
      "vOffset": 100,
      "alignment": "center",
      "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
  }
}    

Each operation was rotated though one of the following search paths:

widget.window.name
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.

Contact

Josh Baker @tidwall

License

SJSON source code is available under the MIT License.

sjson's People

Contributors

cat2neat avatar chen56 avatar dependabot[bot] avatar donatello avatar h8liu avatar hypoactiv avatar jawshua avatar jkearse3 avatar realzhili avatar tidwall avatar ysmood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sjson's Issues

Question - Effective to change multiple values?

This library is fast and awesome, the benchmarks speak for them self.
However, this is only for single value changes.

Is this library still effective compared with other serializers if you need to change multiple values?
And if so, could you provide an effective example?

Delete() removing keys that should not be deleted

When running the following code, both the aaaaaaaaa and nnnnn characters are deleted:

fmt.Println(sjson.Delete("{\"_T\": \"sssssssssssssss\", \"ccccccccc\": {\"name\": \"ttttttttttt\", \"aaaaaaaaa\": \"ttttttt.ttttt\", \"nnnnn\": \"4000\"}}", "ccccccccc.nnnnn"))

> {"_T": "sssssssssssssss", "ccccccccc": {"name": "ttttttttttt"}}

Deleting fields that contain full stops cannot be deleted

Hello, I'm using sjson to modify the JSON representation of kubernetes objects. Many of them contain this field:

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": ""
    }
}

I want to target the kubectl.kubernetes.io/last-applied-configuration to be deleted by sjson. But it seems like due to the . characters in the key, I'm unable to do this with a normal call to sjson.Delete

I've tried both of these:

value, err := sjson.Delete(content, "metadata.annotations.kubectl.kubernetes.io/last-applied-configuration")
value, err := sjson.Delete(content, `metadata.annotations."kubectl.kubernetes.io/last-applied-configuration"`)

But neither result in the field being deleted. Is there a way to perform a deletion on a key that has a full stop in it?

Thanks, great package by the way!

cli interface?

Hi, I just found this project via Hacker News, and wanted to thank you for releasing this!

We have the use case where we want to modify JSON values on disk in the fastest way possible (e.g. perhaps the json could be parsed in a streaming way, and as soon as the path has been found, forget about reading & decoding the rest, but make the change already and abort.

We're currently using elaborate sed regex matching and in-place replacement for this purpose which I'm obviously very ashamed of.

I was wondering if your tool could get a simple cli interface so we could benchmark it against what we currently use? It would be great if we could have something a bit more robust.

That is of course, if you think sjson might indeed be a suitable tool for this this use case?

All the best, Kevin

How to create empty array

Hello

I would like to create empty array, could not find working syntax using "Set" API. e,g. to achieve below json
{
"home": {
"kitchen": {
"refrigerator": []
}
}
}

what would be path syntax in Set API or any other to achieve same?

Niren

Unclear how to escape a dot . in JSON keys

If a JSON key contains a . it's unclear how to escape it if possible.

package main

import (
	"fmt"

	"github.com/tidwall/sjson"
)

func main() {
	value, _ := sjson.Set(`{"app.token":"abc"}`, `app.token`, "cde")
	fmt.Println(value)

	value, _ = sjson.Set(`{"app.token":"abc"}`, `app\.token`, "cde")
	fmt.Println(value)

	value, _ = sjson.Set(`{"apptoken":"abc"}`, `apptoken`, "cde")
	fmt.Println(value)

	// README says "The dot and colon characters can be escaped with ''."
	value, _ = sjson.Set(`{"app.token":"abc"}`, `app''.token`, "cde")
	fmt.Println(value)
}
$ go run main.go
{"app":{"token":"cde"},"app.token":"abc"}
{"app.token":"cde","app.token":"abc"}
{"apptoken":"cde"}
{"app''":{"token":"cde"},"app.token":"abc"}

Expected app.token to be replaced with cde in the second example not created as a duplicate key

Array of bytes

Hello

I am trying to set array of bytes using "Set" or "SetRaw"; unfortunately it returns non array type value for specified path e.g.

  1. Using Set API
    ba := []byte{128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 31, 32, 140}
    value, _ := sjson.Set(``, "byte-array", ba)
    fmt.Println(value)

Returns:
{"byte-array":"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u001f \ufffd"}

  1. Using SetRaw API:
    value, _ := sjson.SetRaw(``, "byte-array", string(ba))
    fmt.Println(value)

Returns:
{"byte-array":"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u001f \ufffd"}

appears that in either case it converts byte array into string. Unfortunately, while retrieving values using gjson returns different values

ret := gjson.Get(value, "byte-array")
fmt.Println("ret: ", ret)

Result:
ret: ������������ �

How to store byte array as pure byte array? like
{"byte-array":[127,126,125,124]}
changing type from "byte" to "uint32" or "uint16" returns result like above.

Thanking You

Niren

Question: Empty Initialised Array vs Uninitialised Array

When an slice is not initialised empty (e.g. var list []string) the value is set as null instead of [].
However if we initialised the slice (e.g. var list := []string{}) the value is set as []

Is this the expected behaviour or a bug? It is inconsistent with the encoding/json which in both cases will produce [].

Below is a simple program that highlights this issue including the output on my system. The output test3 is the one of note, where the array is output as null.

package main

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/sjson"
)

func handleError(err error) {
	if err != nil {
		panic(err)
	}
}

type Example struct {
	Data []string `json:"data"`
}

func main() {

	data := Example{
		Data: []string{"a", "b", "c"},
	}
	raw, err := json.Marshal(data)
	handleError(err)

	fmt.Println("raw: ", string(raw))

	data = Example{
		Data: []string{},
	}
	raw, err = json.Marshal(data)
	handleError(err)

	fmt.Println("raw: ", string(raw))

	sDataArray := []string{"a", "b", "c"}
	test1, err := sjson.SetBytes(raw, "sdata_array", sDataArray)
	handleError(err)

	fmt.Println("test1: ", string(test1))

	sDataArray = []string{}
	test2, err := sjson.SetBytes(raw, "sdata_array", sDataArray)
	handleError(err)

	fmt.Println("test2: ", string(test2))

	var sDataArrayNil []string
	test3, err := sjson.SetBytes(raw, "sdata_array", sDataArrayNil)
	handleError(err)

	fmt.Println("test3: ", string(test3))
}

Output:

raw:  {"data":["a","b","c"]}
raw:  {"data":[]}
test1:  {"data":[],"sdata_array":["a","b","c"]}
test2:  {"data":[],"sdata_array":[]}
test3:  {"data":[],"sdata_array":null}

Setting possibly escaped keys

Hi,
I am storing changes made to documents in key-value format(tidwall/gjson#103)
and I have an issue with escaped keys.

If I call set foo.bar.baz 1 I will store this change as {"foo.bar.baz": 1} but I am not able to store changes if I call set foo\.bar\.baz 1 which should result into {"foo\.bar\.baz": 1} because keys do not have option to set raw value, like values do.

So far the only solutions that come to mind are:

  • using map[string]interface{} for the changes which I would have to convert to json later on, avoiding sjson for changes completely(currently the least intrusive solution)
  • base64-encoding the keys
  • using different delimiter on insert and then replacing it with dot upon parsing

... but I would prefer avoiding workarounds with something like SetOptions()

when i update to 1.1.0, error

{
"_source": [
"_id"
],
"from": 0,
"query": {
"bool": {
"must_not": [
{
"term": {
"is_deleted": true
}
}
],
"filter": [
{
"terms": {
"_id": [
"56d87325dabfae2eee03f325",
"58774c630a3ac5b5de64f6a2"
]
}
}
]
}
},
"size": 1000,}
"aggs": {
"sample": {
"aggs": {
"org": {
"terms": {
"field": "authors.org.keyword",
"execution_hint": "map",
"size": 20
}
}
}
}
}
}

when i use SetRaw(str,"aggs",aggStr) it return me result above.

v1.2.0 breaks updating keys beginning with @

Hello

version 1.2.0+ which added "updates of complex paths" breaks updating keys beginning with the @ symbol.

Example:

data, err := sjson.SetBytes([]byte(`{"Test":123}`), "@timestamp", time.Now().Unix())
if err != nil {
	log.Fatal(err)
}

Current Result:
{"Test":123}

Expected:
{"Test":123,"@timestamp":1639152890}

Is there a workaround?

Tag version

Release a version with Semantic versioning, please.

Bug - Missing quotes?

var json = []byte(`{"message":""}`)
var path = "message"
var value = []byte("Hello, World!")
var opt = &sjson.Options{
  Optimistic: false,
}

raw, _ := sjson.SetRawBytesOptions(json, path, value, opt)
fmt.Println(string(json))
// => {"message":Hello, World!}

Allow modification based on specified path

trying to give an example. In an array of objects, can we have support for updating one object based on specifying attribute and value of individual object in the array.

{
"attrs": [{
"name": "location",
"value": "Chicago"
}, {
"name": "address",
"value": "Magnificent Mile"
}, {
"name": "count",
"value": "50"
}]
}

value, _ := sjson.Set("attrs#(name=="location")", "Lewisville")

Delete not reliable

Occasionally when we delete a field, the function deletes the field before, in addition to the intended field.

A demonstration unit test is attached of the function sjson.Delete
sjson_test.go.zip

Why can't this scenario assign a value to a list?

type StudentInfo struct {
	StudentId string   `json:"student_id"`
	Class     []string `json:"class"`
}

type Item struct {
	StudentInfo []*StudentInfo `json:"student_info"`
}

func main() {
	item := &Item{
		[]*StudentInfo{
			{
				StudentId: "1",
				Class:     []string{"class1"},
			},
		},
	}
	itemBytes, _ := json.Marshal(item)
	ret, _ := sjson.Set(string(itemBytes), `student_info.#(student_id=="1").class.-1`, "class2")
	fmt.Println(ret)
}

my desired result is {"student_info":[{"student_id":"1","class":["class1","class2"]}]},but the actual result is {"student_info":[{"student_id":"1","class":["class1"]}]}

Feature request - allow sets via array accessors

It'd be really handy to be able to set fields using the following array syntax in the same way gjson allows for gets via the syntax:

body := `{
	"people": [
		{ "id": 1, "name": "alice" },
		{ "id": 2, "name": "bob" }
	]
}`

body, err := sjson.Set(body, `people.#[id="1"].name`, "carol")
if err != nil {
	log.Fatal(err)
}

fmt.Println(body)

Is this something that could be added to the library?

DeleteBytes not working well for paths with escaped dot inside

I am able to read the data with gjson.GetBytes but have trouble to delete the data with sjson.DeleteBytes. See example below:

package main

import (
    "fmt"
    "encoding/json"

    "github.com/tidwall/gjson"
    "github.com/tidwall/sjson"
)

func main() {
    parameters := &map[string]interface{}{
	"data": map[string]interface{}{
	    "key1":     "value1",
	    "key2.something": "value2",
        },
    }

    path := "data.key2\\.something"

    data, err := json.Marshal(parameters)
    if err != nil {
        fmt.Println(err)
    }

    // Read
    res := gjson.GetBytes(data, path)
    if !res.Exists() {
        fmt.Println("res does not exist")
    }
    fmt.Println("res", res.Value())

    // Delete
    data, err = sjson.DeleteBytes(data, path)
    var params interface{}
    err = json.Unmarshal(data, &params)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("params", params)
}

Can't set numbered keys

In gjson, I can get the value of a numbered key, for example

gjson.Get("{\"foo\":{\"1\": 10}}", "foo.1")

However, in sjson, because of the way array values are set, I can't set the same key. Is there a way to get around this?

Here is the reproduction script

package main

import (
	"fmt"
	"github.com/tidwall/sjson"
)

func main() {
	str, _ := sjson.Set("{}", "foo.bar", 10)
	fmt.Println(str) // {"foo":{"bar":10}}

	str, _ = sjson.Set("{}", "foo.1", 10)
	fmt.Println(str) // {"foo":[null,10]}
}

Modify a data from list based on condition

Hi, I would want to modify a specific data from Slice of JSON. Is it possible in sjson?

{
    "app": "gfgeeks",
    "prop": [
          {"region": 736,"set": true,"score": 72},
          {"region": 563,"set": true,"score": 333},     // modify score to 334; if region == 563 && set == true
          {"region": 563,"set": false,"score": 333}
    ],
    "index" : "haskell"
}

I'm currently using gjson to get the json object and I'm able to modify the score to 334. While trying to replace the json back in list, I would want to delete {"region": 563,"set": true,"score": 333} element and add {"region": 563,"set": true,"score": 334}. Currently, sjson is letting me to delete only positional parameter. For example, I could do sjson.Delete(JSON, prop.1) would work. But, the position would often vary. So, I cannot use this approach.

Playground : https://play.golang.org/p/lZu9LezD3Wn

@tidwall

Mismatched Encoding / Decoding of Byte Values

great project, thanks for your contribution to open source!

i'm consistently experiencing some unusual behavior when setting byte values (the impacted code is here and here): when byte values are set, they are converted to a string and then (by default) encoded using the standard library's json.Marshal function, but (for reasons i don't understand) it appears that json.Unmarshal does not decode the value back to the original byte value. here's an example showing how SJSON's behavior mimics the behavior of the standard library, plus a "working example" using strconv to get the original bytes.

as an aside, was it a design decision for SJSON to not encode bytes as a base64 encoded string? that is how the standard library works and it would also solve the problem of consistently decoding back to the original value.

thanks!

JSON anonymous object

[
{
    "client_id": 1000,
    "edge_ip": "xx.xx.xx.xx",
    "edge_port": port1,
    "timestamp":123456
},
{
    "client_id": 1001,
    "edge_ip": "yy.yy.yy.yy",
    "edge_port": port2,
    "timestamp":123456
}
]

How can I set the client_id with sjson?

Backslashes aren't escaped properly when setting string values

When setting a path to a string value that contains a backslash the backslash won't be escaped, which produces invalid JSON.

For example, encoding the value C:\Windows\System32 produces the following result:

Go:       {"path":"C:\\Windows\\System32"}
sjson:    {"path":"C:\Windows\System32"}

Attempting to unmarshal the sjson output results in invalid character 'W' in string escape code.

Here's a gist that reproduces the error:
https://gist.github.com/Jawshua/a221a3293215c1b9631f379a17542a6a

I suspect the error is in the mustMarshalString function, which is only triggering escaping for slashes if the slash is the last character in the string.

How can I append key value?

What function Set does is always prepends key value to a given json object (not an array).
Is there any way to put it in the end of json?

JSON-LD path with multiple @ keywords fails

I trying to write a line where I update a context entry in a JSON-LD document. The schema.org context is often either https://schema.org or http://schema.org. This is some code to normalize them to a value.

In the code at https://github.com/gleanerio/gleaner/blob/df--dev/tools/contextChange/main.go line 118 I have

jsonld, err = sjson.Set(jsonld, tns, sdoc)

When this has a value for tns like:

@context.@vocab

It will not update the JSON document (they are in the data directory next to the go main file)

if it is

@context.schema

it entry is found and updated.

It seems is the second element have an @ keyword prefix (ie, the @vocab) cause sjon to not find the entry.

Any guidance is appreciated

possible memory leak using sjson.Set

Hi @tidwall
I'm using this library to enrich event without unmarshalling into Go struct, and there's seems to be a memory problem in sjson.Set().
This is how I use it:

func EnrichEvent(event string, ctx *fasthttp.RequestCtx) string {
	startTime := time.Now().UnixNano() / 1000000

	log := zap.L()

	ua := string(ctx.UserAgent())
	ip := ctx.RemoteIP().String()
	entryTs := strconv.Itoa(int(time.Now().UnixNano() / int64(time.Millisecond)))

	var err error

	// add new fields to events
	event, err = sjson.Set(event, "ua", ua)
	if err != nil {
		log.Error("could not add ua to event", zap.String("event", event), zap.Error(err))
	}

	event, err = sjson.Set(event, "client_ip", ip)
	if err != nil {
		log.Error("could not add client_ip to event", zap.String("event", event), zap.Error(err))
	}

	event, err = sjson.Set(event, "entry_ts", entryTs)
	if err != nil {
		log.Error("could not add entry_ts to event", zap.String("event", event), zap.Error(err))
	}

	endTime := time.Now().UnixNano() / 1000000
	promy.RecordMetric("EnrichTimeHistogram", 0, float64(endTime-startTime), nil)

	return event
}

and when I'm trying to profile the allocs, it looks like sjson keeps growing and growing:
allocs

am I doing anything wrong?

SetBytes with string slice as value is escaped

Hello

I want to set a string slice as a value with SetBytes. Unfortunately the JSON marshaler seems to escape the quotes:
{"data": "[\"test1\"]"}

How can I prevent this?

The expected result would be:
{"data": ["test1"]}

Need to set array of values to array of objects.

need to set multiple values for an array of objects

package main

import (
	"fmt"

	"github.com/tidwall/sjson"
)

const jsondata = `{"data":[]}`

func main() {
	data := make([]string, 0)
	data = append(data, "sos", "msa", "kkh")
	value, err := sjson.Set(jsondata, "data.#.name", data)
	if err != nil {
		fmt.Println(err)
	}
	println(value)

}

expected result

{data:[{name:"sos"},{name:"msa"},{name:"kkh"}]

output result

{"data":[]}

from my understanding of the source code, I have observed that the value is converted to a string and replaced at the exact path.
is there any possible way to implement this?. However, we will be able to map the array by providing an index number instead of #

value, err := sjson.Set(jsondata, "data.0.name", data[0])
value, err = sjson.Set(value, "data.1.name", data[1])

Set value type error!

sjson.Set(b.content, path, []uint8{1, 2, 3, 4})
value type "[]uint8" will change to "string"

How to sort json

Hi, i am the json funner, it's a very good library. but when i use it, there is a problem about sort json objects
so i need your help. thank you very much!

Confusing doc for ReplaceInPlace field of Options

Per the doc, regarding the ReplaceInPlace field of the Options struct :

There is no guarentees that the memory will be replaced in-place.

I first found this sentence strange, then goes to read the code (https://github.com/tidwall/sjson/blob/master/sjson.go#L413), and I think it could be better expressed, explaining that if the destination slice doesn't have enough free bytes to replace the data in place, a new bytes slice will be created under the hood.

Feature request: Querying Path

Hi,

like in gjson:

name := gjson.Get(json, `programmers.#[lastName="Hunter"].firstName`)
println(name.String())  // prints "Elliotte"

It would be nice if one could set a field by querying for it. because right now I would like to update an object within an array. and I don't know the index beforehand.

any plans to implement this?

the key is ip ,how to do?

{
"192.168.0.1":"aaa",
"192.168.0.2":"bbb"
}

json01 := gjson.Get(jsonstring, "data")
for k, v := range json01.Map() {
json02, _ = sjson.Set(jsonstring, k, "hello")
}

I to try

kip := strings.Replace(k, ".", "\\.", -1)

but not working

Search / Find

Hi,

Lets say;

Json = `{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":37,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
	{"first": "James", "last": "Murphy"},
	{"first": "Roger", "last": "Craig"}
  ]
},{
  "name": {"first": "Tom", "last": "Anderson"},
  "age":35,
  "children": ["Sara","Alex","Jack"],
  "fav.movie": "Deer Hunter",
  "friends": [
	{"first": "James", "last": "Murphy"},
	{"first": "Roger", "last": "Craig"}
  ]
}`

this is an array version of the example used at readme, but here first age is 37 and second age is 35
How i can change name.first of age 35?

Is there a search of value like gjson?
Get("#(age==35)")

Benchmarks

I (and probably many others) would love to see some benchmarks compared to other libraries, like you did with gjson. Thanks!

If we dont know the full path, how we specify it?

I have an unstructured dynamic object. So I can not know the path. It is like following:
{

	"temp1": {
		"temp2": {
			"password": "123456",
			"country": "turkey",
			"temp3": {
				"password": "789654"
			}
		}
	}
}

I want to edit password values to "secret", but in my program I dont know the path. Can I use prefix-posfix etc... How can i handle this problem?

Feature request: ability to use customized json marshaler

When a type is not recognized, SJSON will fallback to the encoding/json Marshaller.

The standard json library doesn't support type registration, so it's not very ideal to handle complex or customized struct marshaling.
I'd like to have a package level variable in sjson holding a global json marshaler which will be used when a type is not recognized.
Or, we can add a new option in SetOptions specifying the marshaler used for this Set call ?
I prefer the former way, maybe we can add them both ?

Feature request: Set a value with an object/array

Would it be possible to set a value to an object/array?
So don't escape the string value if it starts with "{" | "[" and ends with "}" | "]".

value, _ := sjson.Set(`{"name":"Andy"}`, "friends", `["Carol","Sara"]')
println(value)

// Output:
// {"name":"Andy","friends":["Carol","Sara"]}
value, _ := sjson.Set(`{"name":"Andy"}`, "meta", `{"gender":"M","age":42}`)
println(value)

// Output:
// {"name":"Andy","meta":{"gender":"M","age":42}}

Or append an object/array to an existing array?

value, _ := sjson.Set(`{"friends":[{"name":"Andy","age": 8},{"name":"Carol","age":7}]}`, "friends.-1", `{"name":"Sara","age":8}`)
println(value)

// Output:
// {"friends":[{"name":"Andy","age": 8},{"name":"Carol","age":7},{"name":"Sara","age":8}]}

Thanks in advance!

Question on behavior of sjson

can you explain the behavior of below code?

https://play.golang.org/p/0GkEaE0hdq1

the given code is giving output as

$go run main.go
JSON:{"node":"{"name":"xxxx"}"}
JSON1:{"node":"{"childs":[{"lastname":"yyyyy"}]"}

it is replacing the string output got from line#10.

if i change the line#16 and use the hardcoded string "{"node":"{"name":"xxxx"}"}" in place newjson then it is returning the output as below.

{"node":"{"childs":[{"lastname":"yyyyy"}],"name":"xxxx""}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.