-
Notifications
You must be signed in to change notification settings - Fork 23
/
gojq.go
159 lines (146 loc) · 4.07 KB
/
gojq.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package gojq
import (
"encoding/json"
"errors"
"fmt"
"os"
"strconv"
"strings"
"github.com/elgs/gosplitargs"
)
// JQ (JSON Query) struct
type JQ struct {
Data any
}
// NewFileQuery - Create a new &JQ from a JSON file.
func NewFileQuery(jsonFile string) (*JQ, error) {
raw, err := os.ReadFile(jsonFile)
if err != nil {
return nil, err
}
var data = new(any)
err = json.Unmarshal(raw, data)
if err != nil {
return nil, err
}
return &JQ{*data}, nil
}
// NewStringQuery - Create a new &JQ from a raw JSON string.
func NewStringQuery(jsonString string) (*JQ, error) {
var data = new(any)
err := json.Unmarshal([]byte(jsonString), data)
if err != nil {
return nil, err
}
return &JQ{*data}, nil
}
// NewQuery - Create a &JQ from an any parsed by json.Unmarshal
func NewQuery(jsonObject any) *JQ {
return &JQ{Data: jsonObject}
}
// Query queries against the JSON with the expression passed in. The exp is separated by dots (".")
func (jq *JQ) Query(exp string) (any, error) {
if exp == "." {
return jq.Data, nil
}
paths, err := gosplitargs.SplitArgs(exp, ".", false)
if err != nil {
return nil, err
}
var context any = jq.Data
for _, path := range paths {
if len(path) >= 3 && strings.HasPrefix(path, "[") && strings.HasSuffix(path, "]") {
// array
index, err := strconv.Atoi(path[1 : len(path)-1])
if err != nil {
return nil, err
}
if v, ok := context.([]any); ok {
if len(v) <= index {
return nil, errors.New(fmt.Sprint(path, " index out of range."))
}
context = v[index]
} else {
return nil, errors.New(fmt.Sprint(path, " is not an array. ", v))
}
} else {
// map
if v, ok := context.(map[string]any); ok {
if val, ok := v[path]; ok {
context = val
} else {
return nil, errors.New(fmt.Sprint(path, " does not exist."))
}
} else {
return nil, errors.New(fmt.Sprint(path, " is not an object. ", v))
}
}
}
return context, nil
}
// QueryToMap queries against the JSON with the expression passed in, and convert to a map[string]any
func (jq *JQ) QueryToMap(exp string) (map[string]any, error) {
r, err := jq.Query(exp)
if err != nil {
return nil, errors.New("Failed to parse: " + exp)
}
if ret, ok := r.(map[string]any); ok {
return ret, nil
}
return nil, errors.New("Failed to convert to map: " + exp)
}
// QueryToMap queries against the JSON with the expression passed in, and convert to a array: []any
func (jq *JQ) QueryToArray(exp string) ([]any, error) {
r, err := jq.Query(exp)
if err != nil {
return nil, errors.New("Failed to parse: " + exp)
}
if ret, ok := r.([]any); ok {
return ret, nil
}
return nil, errors.New("Failed to convert to array: " + exp)
}
// QueryToMap queries against the JSON with the expression passed in, and convert to string
func (jq *JQ) QueryToString(exp string) (string, error) {
r, err := jq.Query(exp)
if err != nil {
return "", errors.New("Failed to parse: " + exp)
}
if ret, ok := r.(string); ok {
return ret, nil
}
return "", errors.New("Failed to convert to string: " + exp)
}
// QueryToMap queries against the JSON with the expression passed in, and convert to int64
func (jq *JQ) QueryToInt64(exp string) (int64, error) {
r, err := jq.Query(exp)
if err != nil {
return 0, errors.New("Failed to parse: " + exp)
}
if ret, ok := r.(float64); ok {
return int64(ret), nil
}
return 0, errors.New("Failed to convert to int64: " + exp)
}
// QueryToMap queries against the JSON with the expression passed in, and convert to float64
func (jq *JQ) QueryToFloat64(exp string) (float64, error) {
r, err := jq.Query(exp)
if err != nil {
return 0, errors.New("Failed to parse: " + exp)
}
if ret, ok := r.(float64); ok {
return ret, nil
}
return 0, errors.New("Failed to convert to float64: " + exp)
}
// QueryToMap queries against the JSON with the expression passed in, and convert to bool
func (jq *JQ) QueryToBool(exp string) (bool, error) {
r, err := jq.Query(exp)
if err != nil {
return false, errors.New("Failed to parse: " + exp)
}
if ret, ok := r.(bool); ok {
return ret, nil
}
return false, errors.New("Failed to convert to float64: " + exp)
}