Based on https://github.com/savaki/jq
Use reflect package and jq syntax to modify golang struct
package main
import (
"fmt"
"reflect"
"github.com/blippar/jq"
)
func main() {
data := struct {
A map[string][]int `json:"field"`
}{
A: map[string][]int{
"here": []int{1},
},
}
// create an Op
// op := Dot("field", Dot("here", Addition(json.RawMessage("[3]"))))
op, _ := jq.Parse(".field.here+=[3]")
// Apply the op to data
value, _ := op.Apply(reflect.ValueOf(&data))
fmt.Printf("data: %v\n", data)
fmt.Printf("value: %v\n", value)
}
// value is of type reflect.Value,
// value.Interface() will return underlying type
//
// output:
// data: {map[here:[1 3]]}
// value: [1 3]The initial goal is to support all the selectors the original jq command line supports.
| syntax | meaning |
|---|---|
| . | unchanged input |
| .foo | value at key |
| .foo.bar | value at nested key |
| .[0] | value at specified element of array |
| .[0:1] | array of specified elements of array, inclusive |
| .foo.[0] | nested value |
| .= | set value |
| .+= | add value to string and slice |
struct {
String string
Number float32
Simple []string
Mixed []interface{}
Struct struct {
A string
B []int
}
Map map[string]interface{}
WithJSONTag int `json:"tagged"`
}{
String: "a",
Number: 1.23,
Simple: []string{"a", "b", "c"},
Mixed: []interface{}{
"d",
2,
map[string]string{"hello": "world"},
},
Struct: struct {
A string
B []int
}{
A: "e",
B: []int{3, 4, 5},
},
Map: map[string]interface{}{"f": []int{6, 7, 8}},
WithJSONTag: 9,
}| syntax | value |
|---|---|
| .string | "a" |
| .number | 1.23 |
| .simple | ["a", "b", "c"] |
| .simple.[0] | "a" |
| .simple = ["d"] | ["d"] |
| .simple += ["d"] | ["a", "b", "c", "d"] |
| .simple = "d" | <Error> |
| .simple.[0:1] | ["a","b"] |
| .mixed.[2].hello | "world" |
| .Struct.a | "e" |
| .tagged | 9 |
For these two, the parameter reflect.Value can be set ( val.CanSet() == true )
or it is an interface / ptr, result of Elem can be set ( val.Elem().CanSet() == true )
Set = will assign the value to another, if they are not of the same type it will return an error.
Addition += will concat the value to the one provided, if they are not of the same type it will return an error