collectjs
Convenient and dependency free wrapper for working with json arrays and objects in go. Like collect.js
You can transform json
data format and convert it into a suitable data
structure without using json.Marshal
and json.Unmarshal
.
How to use
import "github.com/tkeel-io/collectjs"
var raw = Byte(`[
{
"count": "1",
"product": "Chair",
"manufacturer": "IKEA"
},
{
"sum": "10",
"product": "Desk",
"manufacturer": "IKEA"
},
{
"product": "Chair",
"manufacturer": "Herman Miller"
}
]`)
func main(){
cc := newCollect(raw)
fmt.Println(string(cc.MergeBy("product", "manufacturer")))
// Output:
// {
// "Chair+IKEA":{"count": "1","product": "Chair","manufacturer": "IKEA"},
// "Desk+IKEA":{"sum": "10","product": "Desk","manufacturer": "IKEA"},
// "Chair+Herman Miller":{"product": "Chair","manufacturer": "Herman Miller"}
// }
fmt.Println(string(MergeBy(raw, "product", "manufacturer")))
// Output:
// {
// "Chair+IKEA":{"count": "1","product": "Chair","manufacturer": "IKEA"},
// "Desk+IKEA":{"sum": "10","product": "Desk","manufacturer": "IKEA"},
// "Chair+Herman Miller":{"product": "Chair","manufacturer": "Herman Miller"}
// }
}
API
All available methods
Get
func TestCollect_Get(t *testing.T) {
tests := []struct {
name string
raw []byte
path string
want interface{}
}{
{"1", raw, "", string(raw)},
{"2", raw, "cpu", "1"},
{"2.1", raw, "mem[0]", "\"lo0\""},
{"3", raw, "a", `[{"v":0},{"v":1},{"v":2}]`},
{"4", raw, "a[0]", `{"v":0}`},
{"5", raw, "a[1]", `{"v":1}`},
{"6", raw, "a[2]", `{"v":2}`},
{"7", raw, "a[#]", `3`}, // count
{"8", raw, "a[#].v", `[0,1,2]`},
{"9", raw, "b[0].v", `{"cv":1}`},
{"10", raw, "b[1].v", `{"cv":2}`},
{"11", raw, "b[2].v", `{"cv":3}`},
{"12", raw, "b[#].v", `[{"cv":1},{"cv":2},{"cv":3}]`},
{"13", raw, "b[1].v.cv", `2`},
{"14", raw, "b[#].v.cv", `[1,2,3]`},
{"14", rawArray, "[0]", `{"v":{"cv":1}}`},
}
for _, tt := range tests {
cc := newCollect(tt.raw)
t.Run(tt.name, func(t *testing.T) {
if got := cc.Get(tt.path); !reflect.DeepEqual(string(got.raw), tt.want) {
t.Errorf("Get() = %v, want %v", string(got.raw), tt.want)
}
})
}
}
Set
func TestCollect_Set(t *testing.T) {
tests := []struct {
name string
path string
value string
want interface{}
}{
{"2", "cpu", "2", `{"cpu":2,"mem": ["lo0", "eth1", "eth2"],"a":[{"v":0},{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"3", "a", `{"v":0}`, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":{"v":0},"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"4", "a[0]", `0`, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":[0,{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"5", "a[0].v", `{"v":0}`, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":[{"v":{"v":0}},{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cc := newCollect(raw)
cc.Set(tt.path, []byte(tt.value))
if got := cc.raw; !reflect.DeepEqual(string(got), tt.want) {
t.Errorf("Get() = %v, want %v", string(got), tt.want)
}
})
}
}
Append
func TestCollect_Append(t *testing.T) {
tests := []struct {
name string
raw []byte
path string
value string
want interface{}
}{
{"1", raw, "cpu", "2", `Unknown value type`},
{"2", raw, "mem", "2", `{"cpu":1,"mem": ["lo0", "eth1", "eth2",2],"a":[{"v":0},{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"3", raw, "a", `{"v":11}`, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":[{"v":0},{"v":1},{"v":2},{"v":11}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"4", raw, "a[0]", `0`, `Unknown value type`},
{"5", raw, "a[0].v", `{"v":0}`, `Unknown value type`},
{"5", rawEmptyArray, "", `{"v":0}`, `[{"v":0}]`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cc := newCollect(tt.raw)
cc.Append(tt.path, []byte(tt.value))
if got := cc.raw; !reflect.DeepEqual(string(got), tt.want) {
t.Errorf("Get() = %v, want %v", string(got), tt.want)
}
})
}
}
Del
func TestCollect_Del(t *testing.T) {
tests := []struct {
name string
path []string
want interface{}
}{
{"2", []string{"cpu"}, `{"mem": ["lo0", "eth1", "eth2"],"a":[{"v":0},{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"3", []string{"a", "b", "cpu"}, `{"mem": ["lo0", "eth1", "eth2"],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"4", []string{"a[0]"}, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":[{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
{"5", []string{"a[0].v"}, `{"cpu":1,"mem": ["lo0", "eth1", "eth2"],"a":[{},{"v":1},{"v":2}],"b":[{"v":{"cv":1}},{"v":{"cv":2}},{"v":{"cv":3}}],"where": 10,"metadata": {"name": "Light1", "price": 11.05}}`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cc := newCollect(raw)
cc.Del(tt.path...)
if got := cc.raw; !reflect.DeepEqual(string(got), tt.want) {
t.Errorf("Get() = %v, want %v", string(got), tt.want)
}
})
}
}
Combine
func Example_Combine() {
collection := []byte(`["name", "number"]`)
collection2 := []byte(`["Mohamed Salah", 11]`)
combine, _ := Combine(collection, collection2)
fmt.Println(string(combine))
// Output:
// {"name":"Mohamed Salah","number":11}
}
GroupBy
func Example_GroupBy() {
ret, _ := GroupBy(rawGroup, "manufacturer") //node_memory_MemTotal_bytes
fmt.Println(string(ret))
// Output:
// {"IKEA":[{"count": "1","product": "Chair","manufacturer": "IKEA"},{"sum": "10","product": "Desk","manufacturer": "IKEA"}],"Herman Miller":[{"product": "Chair","manufacturer": "Herman Miller"}]}
}
MergeBy
func Example_MergeBy() {
ret, _ := MergeBy(rawGroup, "product", "manufacturer") //node_memory_MemTotal_bytes
fmt.Println(string(ret))
// Output:
// {"Chair+IKEA":{"count": "1","product": "Chair","manufacturer": "IKEA"},"Desk+IKEA":{"sum": "10","product": "Desk","manufacturer": "IKEA"},"Chair+Herman Miller":{"product": "Chair","manufacturer": "Herman Miller"}}
}
KeyBy
func Example_KeyBy() {
ret, _ := KeyBy(rawGroup, "manufacturer") //node_memory_MemTotal_bytes
fmt.Println(string(ret))
// Output:
// {"IKEA":{"sum": "10","product": "Desk","manufacturer": "IKEA"},"Herman Miller":{"product": "Chair","manufacturer": "Herman Miller"}}
}
Merge
func Example_Merge() {
var rawObject1 = Byte(`{"id": 1,"price": 29,}`)
var rawObject2 = Byte(`{"price": "229","discount": false}`)
ret, _ := Merge(rawObject1, rawObject2)
fmt.Println(string(ret))
// Output:
// {"id": 1,"price": "229",,"discount":false}
}
Demo
You can receive Prometheus data format and convert it into a suitable data structure without using json.Marshal
and json.Unmarshal
.
func Example_Demo() {
collection1 := New(`{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.14.102:9100","job":"linux"},"value":[1620999810.899,"6519189504"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.14.146:9100","job":"linux"},"value":[1620999810.899,"1787977728"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.21.163:9100","job":"linux"},"value":[1620999810.899,"5775802368"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.21.174:9100","job":"linux"},"value":[1620999810.899,"19626115072"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"localhost:9100","job":"linux"},"value":[1620999810.899,"3252543488"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.14.102:9100","job":"linux"},"value":[1620999810.899,"8203091968"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.14.146:9100","job":"linux"},"value":[1620999810.899,"8203091968"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.21.163:9100","job":"linux"},"value":[1620999810.899,"8202657792"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.21.174:9100","job":"linux"},"value":[1620999810.899,"25112969216"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"localhost:9100","job":"linux"},"value":[1620999810.899,"3972988928"]}]}}`)
result := collection1.Get("data.result")
result.Map(func(key []byte, bytes []byte) []byte {
val := New("{}")
val.Set("timestamp", Get(bytes, "value[0]"))
val.Set("value", Get(bytes, "value[1]"))
ret := New("{}")
ret.Set(string(Get(bytes, "metric.__name__")), val.raw)
ret.Set("instance", Get(bytes, "metric.instance"))
return ret.raw
})
ret, _ := GroupBy(result.raw, "instance") //node_memory_MemTotal_bytes
metricValue := func(p1, p2 *Collect) bool {
return bytes.Compare(p1.Get("[0]").raw, p2.Get("[0]").raw) > 0
}
newCollect(ret).SortBy(metricValue)
fmt.Println(string(result.raw))
// Output:
// [{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"6519189504"},"instance":"192.168.14.102:9100"},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"1787977728"},"instance":"192.168.14.146:9100"},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"5775802368"},"instance":"192.168.21.163:9100"},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"19626115072"},"instance":"192.168.21.174:9100"},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"3252543488"},"instance":"localhost:9100"},{"node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8203091968"},"instance":"192.168.14.102:9100"},{"node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8203091968"},"instance":"192.168.14.146:9100"},{"node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8202657792"},"instance":"192.168.21.163:9100"},{"node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"25112969216"},"instance":"192.168.21.174:9100"},{"node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"3972988928"},"instance":"localhost:9100"}]
}
func Example_Demo2() {
collection1 := New(`{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.14.102:9100","job":"linux"},"value":[1620999810.899,"1"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.14.146:9100","job":"linux"},"value":[1620999810.899,"3"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.21.163:9100","job":"linux"},"value":[1620999810.899,"2"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"192.168.21.174:9100","job":"linux"},"value":[1620999810.899,"19626115072"]},{"metric":{"__name__":"node_memory_MemAvailable_bytes","instance":"localhost:9100","job":"linux"},"value":[1620999810.899,"3252543488"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.14.102:9100","job":"linux"},"value":[1620999810.899,"8203091968"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.14.146:9100","job":"linux"},"value":[1620999810.899,"8203091968"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.21.163:9100","job":"linux"},"value":[1620999810.899,"8202657792"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"192.168.21.174:9100","job":"linux"},"value":[1620999810.899,"25112969216"]},{"metric":{"__name__":"node_memory_MemTotal_bytes","instance":"localhost:9100","job":"linux"},"value":[1620999810.899,"3972988928"]}]}}`)
result := collection1.Get("data.result")
result.Map(func(key []byte, bytes []byte) []byte {
val := New("{}")
val.Set("timestamp", Get(bytes, "value[0]"))
val.Set("value", Get(bytes, "value[1]"))
ret := New("{}")
ret.Set(string(Get(bytes, "metric.__name__")), val.raw)
ret.Set("instance", Get(bytes, "metric.instance"))
return ret.raw
})
ret, _ := MergeBy(result.raw, "instance") //node_memory_MemTotal_bytes
MemAvailable := func(p1, p2 *Collect) bool {
return bytes.Compare(p1.Get("node_memory_MemAvailable_bytes.value").raw, p2.Get("node_memory_MemAvailable_bytes.value").raw) > 0
}
MemTotal := func(p1, p2 *Collect) bool {
return bytes.Compare(p1.Get("node_memory_MemTotal_bytes.value").raw, p2.Get("node_memory_MemTotal_bytes.value").raw) < 0
}
sorted := newCollect(ret)
sorted.SortBy(MemTotal)
sorted.SortBy(MemAvailable)
fmt.Println(string(sorted.raw))
// Output:
// [{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"3252543488"},"instance":"localhost:9100","node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"3972988928"}},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"3"},"instance":"192.168.14.146:9100","node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8203091968"}},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"2"},"instance":"192.168.21.163:9100","node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8202657792"}},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"19626115072"},"instance":"192.168.21.174:9100","node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"25112969216"}},{"node_memory_MemAvailable_bytes":{"timestamp":1620999810.899,"value":"1"},"instance":"192.168.14.102:9100","node_memory_MemTotal_bytes":{"timestamp":1620999810.899,"value":"8203091968"}}]
}
func Example_AAA() {
fmt.Println(gjson.Get(string(rawArray), "0"))
fmt.Println(gjson.Get(string(`["Mohamed Salah", 11]`), "0"))
// Output:
// {"v":{"cv":1}}
//Mohamed Salah
}
License
MIT © Daniel Eckermann