简体   繁体   中英

Add a new key-value pair to a JSON object

I am connecting to an API which gives a rather large json payload. I need to add a key and value to the root object.Once I do ioutil.Readall from the package "net/http" the JSON is a byte array.

My goal is to just simply add to the structure and move on. As an example, the following the pretty similar to what I am doing: https://tutorialedge.net/golang/consuming-restful-api-with-go/

So how can I simply add to a JSON structure another element (key: value)?

If all you want to do is add a key and value to the root object and produce new JSON, and you don't care about having the data in a structure, you can unmarshal into map[string]interface{} , add your value, and then marshal again:

var m map[string]interface{}
err := json.Unmarshal(data, &m)
m["new_key"] = newValue
newData, err := json.Marshal(m)

(I'm not checking for errors, but you should do that of course.) Take a look at https://golang.org/pkg/encoding/json/ for more information about how to deal with JSON in Go.

Since you have a byte data, you need to parse it and store the result in a variable that has your json structure using json.Marshal .

Then after, to add a new key value pair, you can define a new struct with the key and its data type

var variable type1
// Unmarshal the byte data in a variable
json.Unmarshall(data, &variable)
// to add a new key value you can define a new type
type type2 struct {
type1
key type
}
// and you can add
variable2 := type2{variable, newValueToAdd}

While deserializing & reserializing is the more "correct" approach, it may be overkill for just adding a value at the root, which can be done with simple string manipulation (really byte slice manipulation, but the semantics are similar and it's arguably easier):

data := []byte(`{"foo": 1, "bar": true}`)
ins := []byte(`, "baz": "hello"`)    // Note the leading comma.
closingBraceIdx := bytes.LastIndexByte(data, '}')
data = append(data[:closingBraceIdx], ins...)
data = append(data, '}')

This is more error-prone, because it is unaware of JSON syntax entirely, but it's safe enough for most cases and for large JSON documents it is more efficient than a parse, insert, and reserialize.

Playground example: https://play.golang.org/p/h8kL4Zzp7rq

if you want to add key-value of json bytes to new json object, you can use json.RawMessage.

    type Res struct {
        Data interface{}
        Message string
    }

    var row  json.RawMessage
    row = []byte(`{"Name":"xxx","Sex":1}`)
    res := Res{Data:row,Message:"user"}

   
    resBytes ,err := json.Marshal(res)
    println(string(resBytes))
    //print result:"Data":{"Name":"xxx","Sex":1},"Message":"user"}
   

Here's how you can do it in an efficient way while preserving the order of keys in the original JSON. The idea is to use json.RawMessage

// original JSON
bytes := []byte(`{"name": "Adele", "age": 24}`)

// let's try to add the kv pair "country": "USA" to it
type Person struct {
    Bio     json.RawMessage `json:"bio"`
    Country string          `json:"country"`
}

p := Person{
    Bio:     json.RawMessage(bytes), 
    Country: "USA",
}

// ignoring error for brevity
modifiedBytes, _ := json.Marshal(p)
fmt.Println(string(modifiedBytes))

Output:

{"bio":{"name":"Adele","age":24},"country":"USA"}

You can see that the ordering of original JSON is preserved, which wouldn't have been the case if you marshalled the JSON to a map[string]interface{} . This is also more efficient when you're dealing with huge JSONs since there's no reflection involved.

Complete code - https://play.golang.org/p/3hAPVbrAo_w

SJSON package is another way to modify JSON values. In this example :

json:= `{
    "name": {"first":"James","last":"Bond"},
    "age' :40,
    "license" {"Diamond","Gold","Silver"}
    }`

To replace a "Diamond" with "Ultimate"

value, _ := sjson.Set(json, "license.0", "Ultimate")
fmt.Println(value)

json:= `{
        "name": {"first":"James","last":"Bond"},
        "age' :40,
        "license" {"Ultimate","Gold","Silver"}
        }`

Or to add a value "Ultimate" in the end:

value, _ := sjson.Set(json, "license.-1", "Ultimate")
fmt.Println(value)

json:= `{
    "name": {"first":"James","last":"Bond"},
    "age' :40,
    "license" {"Diamond","Gold","Silver","Ultimate"}
    }`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM