1
2
3
4 package jsonpath
5
6 import (
7 "encoding/json"
8 "fmt"
9
10
11
12
13
14 "gopkg.in/yaml.v3"
15 "k8s.io/klog/v2"
16
17 "github.com/spyzhov/ajson"
18 )
19
20
21
22
23
24 func Get(obj map[string]interface{}, expression string) ([]interface{}, error) {
25
26 jsonBytes, err := json.Marshal(obj)
27 if err != nil {
28 return nil, fmt.Errorf("failed to marshal input to json: %w", err)
29 }
30
31 klog.V(7).Info("jsonpath.Get input as json:\n%s", jsonBytes)
32
33
34 root, err := ajson.Unmarshal(jsonBytes)
35 if err != nil {
36 return nil, fmt.Errorf("failed to unmarshal input json: %w", err)
37 }
38
39
40 nodes, err := root.JSONPath(expression)
41 if err != nil {
42 return nil, fmt.Errorf("failed to evaluate jsonpath expression (%s): %w", expression, err)
43 }
44
45 result := make([]interface{}, len(nodes))
46
47
48 for i, node := range nodes {
49
50 jsonBytes, err = ajson.Marshal(node)
51 if err != nil {
52 return nil, fmt.Errorf("failed to marshal jsonpath result to json: %w", err)
53 }
54
55 klog.V(7).Info("jsonpath.Get output as json:\n%s", jsonBytes)
56
57
58 var value interface{}
59 err = yaml.Unmarshal(jsonBytes, &value)
60 if err != nil {
61 return nil, fmt.Errorf("failed to unmarshal jsonpath result: %w", err)
62 }
63 result[i] = value
64 }
65
66 return result, nil
67 }
68
69
70
71
72
73 func Set(obj map[string]interface{}, expression string, value interface{}) (int, error) {
74
75 jsonBytes, err := json.Marshal(obj)
76 if err != nil {
77 return 0, fmt.Errorf("failed to marshal input to json: %w", err)
78 }
79
80 klog.V(7).Info("jsonpath.Set input as json:\n%s", jsonBytes)
81
82
83 root, err := ajson.Unmarshal(jsonBytes)
84 if err != nil {
85 return 0, fmt.Errorf("failed to unmarshal input json: %w", err)
86 }
87
88
89 nodes, err := root.JSONPath(expression)
90 if err != nil {
91 return 0, fmt.Errorf("failed to evaluate jsonpath expression (%s): %w", expression, err)
92 }
93 if len(nodes) == 0 {
94
95 return 0, nil
96 }
97
98
99 for _, node := range nodes {
100 switch typedValue := value.(type) {
101 case bool:
102 err = node.SetBool(typedValue)
103 case string:
104 err = node.SetString(typedValue)
105 case int:
106 err = node.SetNumeric(float64(typedValue))
107 case float64:
108 err = node.SetNumeric(typedValue)
109 case []interface{}:
110 var arrayValue []*ajson.Node
111 arrayValue, err = toArrayOfNodes(typedValue)
112 if err != nil {
113 break
114 }
115 err = node.SetArray(arrayValue)
116 case map[string]interface{}:
117 var mapValue map[string]*ajson.Node
118 mapValue, err = toMapOfNodes(typedValue)
119 if err != nil {
120 break
121 }
122 err = node.SetObject(mapValue)
123 default:
124 if value == nil {
125 err = node.SetNull()
126 } else {
127 err = fmt.Errorf("unsupported value type: %T", value)
128 }
129 }
130 if err != nil {
131 return 0, err
132 }
133 }
134
135
136 jsonBytes, err = ajson.Marshal(root)
137 if err != nil {
138 return 0, fmt.Errorf("failed to marshal jsonpath result to json: %w", err)
139 }
140
141 klog.V(7).Info("jsonpath.Set output as json:\n%s", jsonBytes)
142
143
144 err = yaml.Unmarshal(jsonBytes, &obj)
145 if err != nil {
146 return 0, fmt.Errorf("failed to unmarshal jsonpath result: %w", err)
147 }
148
149 return len(nodes), nil
150 }
151
152 func toArrayOfNodes(obj []interface{}) ([]*ajson.Node, error) {
153 out := make([]*ajson.Node, len(obj))
154 for index, value := range obj {
155
156 jsonBytes, err := json.Marshal(value)
157 if err != nil {
158 return nil, fmt.Errorf("failed to marshal array element to json: %w", err)
159 }
160
161
162 node, err := ajson.Unmarshal(jsonBytes)
163 if err != nil {
164 return nil, fmt.Errorf("failed to unmarshal array element: %w", err)
165 }
166 out[index] = node
167 }
168 return out, nil
169 }
170
171 func toMapOfNodes(obj map[string]interface{}) (map[string]*ajson.Node, error) {
172 out := make(map[string]*ajson.Node, len(obj))
173 for key, value := range obj {
174
175 jsonBytes, err := json.Marshal(value)
176 if err != nil {
177 return nil, fmt.Errorf("failed to marshal map value to json: %w", err)
178 }
179
180
181 node, err := ajson.Unmarshal(jsonBytes)
182 if err != nil {
183 return nil, fmt.Errorf("failed to unmarshal map value: %w", err)
184 }
185 out[key] = node
186 }
187 return out, nil
188 }
189
View as plain text