user320550
user320550

Reputation: 1185

Modifying JSON array of objects

I'm trying to use tidwall/sjson to modify properties in a json object, but getting the following error:

./prog.go:34:77: syntax error: unexpected {, expecting expression

Here's my code:

package main

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

func main() {
    config := `{
                 "root": {
                   "obj1Arr": [
                     {
                       "obj2": {
                         "obj3Arr": [
                           {
                             "key1": "val1",
                             "key2": {
                               "val2": ["a", "b"]
                             }
                           },
                           {
                             "key3": "val3",
                             "key4": "val4"
                           }
                         ]
                       }
                     }
                   ]
                 },
                 "strExample": "bar",
                 "boolExample": true,
                 "floatExample": 12.54
               }`
    value, _ := sjson.Set(config, "root.obj1Arr.0.obj2.obj3Arr", []interface{}[{"hello":"world"}])
    fmt.Println(value)
}

You can reproduce the error with this go playground link. I'm trying to modify the object root.obj1Arr[0].obj2.obj3Arr to simply have a single object inside of it. I'm also trying to work with an unstructured object. How can I fix this error?

Upvotes: 1

Views: 411

Answers (3)

Gavin
Gavin

Reputation: 4515

A slice composite literal is created using {} instead of [] e.g.

value, _ := sjson.Set(config, "root.obj1Arr.0.obj2.obj3Arr", []interface{}{map[string]string{"hello":"world"}})

https://play.golang.org/p/1h07L5KNVTR

Note that you cannot create an anonymous object using composite literal syntax. I chose to use a map[string]string in the example. If your types aren't that simple, or simply aren't known, you can use map[string]interface{} e.g. map[string]interface{}{"my": map[string]interface{}{"nested": []string{"values", "are", "here"}}}

Upvotes: 2

blami
blami

Reputation: 7431

Your []interface{}[{"hello":"world"}] is not valid Go expression as

  1. Slice literal is initialized with []type{...} and not []type[...]
  2. Literal you use to initialize a map inside slice (what you want in object array in JSON) is not valid as it lacks type in front of it, should be: map[string]string{"hello": "world"}

So to modify obj3Arr to be an array of map[string]string the code should be something like:

value, _ := sjson.Set(config, "root.obj1Arr.0.obj2.obj3Arr", []map[string]string{map[string]string{"hello":"world"}})

To work with objects where you don't know structure and types at compile time (as per "I'm also trying to work with an unstructured object" in your question) you will need empty interface{} as type in map instead of string: map[string]interface{}. So that you can store various types in that map values:

value, _ := sjson.Set(config, "root.obj1Arr.0.obj2.obj3Arr", []interface{}{
map[string]interface{}{
    "hello": "world", 
    "key2": true, 
    "listkey": []int{1,2,3,4}, 
    "mapkey": map[int][]bool{1: []bool{true, true, false}}},
})

will produce:

"obj3Arr": [{"hello":"world","key2":true,"listkey":[1,2,3,4],"mapkey":{"1":[true,true,false]}}]

Upvotes: 1

Gopher
Gopher

Reputation: 751

Based on the suggestions changing replacing []interface{}[{"hello":"world"}] with []interface{}{map[string]string{"hello": "world"}}

package main

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

func main() {
    config := `{
                    "root": {
                      "obj1Arr": [
                    {
                  "obj2": {
                      "obj3Arr": [
                        {
                          "key1": "val1",
                          "key2": {
                            "val2": ["a", "b"]
                          }
                            },
                        {
                          "key3": "val3",
                          "key4": "val4"
                        }
                           ]
                  }
                }
                  ]
            },
            "strExample": "bar",
            "boolExample": true,
            "floatExample": 12.54
          }`
    value, _ := sjson.Set(config, "root.obj1Arr.0.obj2.obj3Arr", []interface{}{map[string]string{"hello": "world"}})
    fmt.Println(value)

}

Output:

{
                    "root": {
                      "obj1Arr": [
                        {
                          "obj2": {
                              "obj3Arr": [{"hello":"world"}]
                          }
                        }
                      ]
                    },
                    "strExample": "bar",
                    "boolExample": true,
                    "floatExample": 12.54
                  }

Upvotes: 1

Related Questions