github.com/mithrandie/csvq@v1.18.1/lib/json/query.go (about) 1 package json 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/mithrandie/csvq/lib/value" 8 9 "github.com/mithrandie/go-text/json" 10 ) 11 12 func LoadValue(queryString string, jsontext string) (value.Primary, error) { 13 structure, _, err := load(queryString, jsontext) 14 if err != nil { 15 return nil, err 16 } 17 18 return ConvertToValue(structure), nil 19 } 20 21 func LoadArray(queryString string, jsontext string) ([]value.Primary, error) { 22 structure, _, err := load(queryString, jsontext) 23 if err != nil { 24 return nil, err 25 } 26 27 array, ok := structure.(json.Array) 28 if !ok { 29 return nil, errors.New(fmt.Sprintf("json value does not exists for %q", queryString)) 30 } 31 32 return ConvertToArray(array), nil 33 } 34 35 func LoadTable(queryString string, jsontext string) ([]string, [][]value.Primary, json.EscapeType, error) { 36 structure, et, err := load(queryString, jsontext) 37 if err != nil { 38 return nil, nil, et, err 39 } 40 41 array, ok := structure.(json.Array) 42 if !ok { 43 return nil, nil, et, errors.New(fmt.Sprintf("json value does not exists for %q", queryString)) 44 } 45 46 h, rows, err := ConvertToTableValue(array) 47 return h, rows, et, err 48 } 49 50 func load(queryString string, jsontext string) (json.Structure, json.EscapeType, error) { 51 query, err := Query.Parse(queryString) 52 if err != nil { 53 return nil, 0, err 54 } 55 56 d := json.NewDecoder() 57 d.UseInteger = false 58 data, et, err := d.Decode(jsontext) 59 if err != nil { 60 return nil, et, err 61 } 62 63 st, err := Extract(query, data) 64 return st, et, err 65 } 66 67 func Extract(query QueryExpression, data json.Structure) (json.Structure, error) { 68 var extracted json.Structure 69 var err error 70 71 if query == nil { 72 return data, nil 73 } 74 75 switch query.(type) { 76 case Element: 77 switch data.(type) { 78 case json.Object: 79 element := query.(Element) 80 81 obj := data.(json.Object) 82 if obj.Exists(element.Label) { 83 if element.Child == nil { 84 extracted = obj.Value(element.Label) 85 } else { 86 extracted, err = Extract(element.Child, obj.Value(element.Label)) 87 } 88 } else { 89 extracted = json.Null{} 90 } 91 default: 92 extracted = json.Null{} 93 } 94 case ArrayItem: 95 switch data.(type) { 96 case json.Array: 97 arrayItem := query.(ArrayItem) 98 99 ar := data.(json.Array) 100 if arrayItem.Index < len(ar) { 101 if arrayItem.Child == nil { 102 extracted = ar[arrayItem.Index] 103 } else { 104 extracted, err = Extract(arrayItem.Child, ar[arrayItem.Index]) 105 } 106 } else { 107 extracted = json.Null{} 108 } 109 default: 110 extracted = json.Null{} 111 } 112 case RowValueExpr: 113 switch data.(type) { 114 case json.Array: 115 rowValue := query.(RowValueExpr) 116 if rowValue.Child == nil { 117 extracted = data 118 } else { 119 ar := data.(json.Array) 120 elems := make(json.Array, 0, len(ar)) 121 for _, v := range ar { 122 e, err := Extract(rowValue.Child, v) 123 if err != nil { 124 return extracted, err 125 } 126 elems = append(elems, e) 127 } 128 extracted = elems 129 } 130 default: 131 return extracted, errors.New("json value must be an array") 132 } 133 case TableExpr: 134 switch data.(type) { 135 case json.Object: 136 table := query.(TableExpr) 137 if table.Fields == nil { 138 extracted = json.Array{data} 139 } else { 140 obj := json.NewObject(len(table.Fields)) 141 for _, field := range table.Fields { 142 e, err := Extract(field.Element, data) 143 if err != nil { 144 return extracted, err 145 } 146 147 obj.Add(field.FieldLabel(), e) 148 } 149 extracted = json.Array{obj} 150 } 151 case json.Array: 152 table := query.(TableExpr) 153 var fields []FieldExpr 154 155 if table.Fields != nil { 156 fields = table.Fields 157 } 158 159 array := data.(json.Array) 160 for _, v := range array { 161 obj, ok := v.(json.Object) 162 if !ok { 163 return extracted, errors.New("all elements in array must be objects") 164 } 165 166 if table.Fields == nil { 167 if fields == nil { 168 fields = make([]FieldExpr, 0, obj.Len()) 169 } 170 for _, members := range obj.Members { 171 if !existsKeyInFields(members.Key, fields) { 172 fields = append(fields, FieldExpr{Element: Element{Label: members.Key}}) 173 } 174 } 175 } 176 } 177 178 elems := make(json.Array, 0, len(array)) 179 for _, v := range array { 180 obj := json.NewObject(len(fields)) 181 for _, field := range fields { 182 e, err := Extract(field.Element, v) 183 if err != nil { 184 return extracted, err 185 } 186 187 obj.Add(field.FieldLabel(), e) 188 } 189 elems = append(elems, obj) 190 } 191 extracted = elems 192 default: 193 return extracted, errors.New("json value must be an array or object") 194 } 195 default: 196 return extracted, errors.New("invalid expression") 197 } 198 199 return extracted, err 200 } 201 202 func existsKeyInFields(key string, list []FieldExpr) bool { 203 for _, v := range list { 204 if key == v.Element.Label { 205 return true 206 } 207 } 208 return false 209 }