|
1 |
| -jsonquery |
2 |
| -==== |
| 1 | +# jsonquery |
| 2 | + |
3 | 3 | [](https://travis-ci.org/antchfx/jsonquery)
|
4 | 4 | [](https://coveralls.io//antchfx/jsonquery?branch=master)
|
5 | 5 | [](https://godoc.org/.com/antchfx/jsonquery)
|
6 | 6 | [](https://goreportcard.com/report/.com/antchfx/jsonquery)
|
7 | 7 |
|
8 |
| -Overview |
9 |
| -=== |
10 |
| - |
11 |
| -jsonquery is an XPath query package for JSON document, lets you extract data from JSON documents through an XPath expression. Built-in XPath expression cache avoid re-compile XPath expression each query. |
| 8 | +# Overview |
12 | 9 |
|
| 10 | +[jsonquery](https://.com/antchfx/jsonquery) is XPath query package for JSON document depended on [xpath](https://.com/antchfx/xpath) package, writing in go. |
13 | 11 |
|
14 |
| -XPath query for Golang |
15 |
| -=== |
| 12 | +jsonquery helps you easy to extract any data from JSON using XPath query without using pre-defined object structure to unmarshal in go, saving your time. |
16 | 13 |
|
17 | 14 | - [htmlquery](https://.com/antchfx/htmlquery) - XPath query package for HTML document
|
18 | 15 |
|
19 | 16 | - [xmlquery](https://.com/antchfx/xmlquery) - XPath query package for XML document.
|
20 | 17 |
|
21 |
| -- [jsonquery](https://.com/antchfx/jsonquery) - XPath query package for JSON document |
| 18 | +### Install Package |
22 | 19 |
|
| 20 | +``` |
| 21 | +go get .com/antchfx/jsonquery |
| 22 | +``` |
23 | 23 |
|
24 |
| -Getting Started |
25 |
| -=== |
| 24 | +## Get Started |
26 | 25 |
|
27 |
| -### Install Package |
| 26 | +The below code may be help your understand what it does. We don't need pre-defined strcutre or using regexp to extract some data in JSON file, gets any data is easy and fast in jsonquery now. |
| 27 | + |
| 28 | +```go |
| 29 | +s := `{ |
| 30 | +"name":"John", |
| 31 | +"age":31, |
| 32 | +"female":false, |
| 33 | +"city":null |
| 34 | +}` |
| 35 | +doc, err := jsonquery.Parse(strings.NewReader(s)) |
| 36 | +if err != nil { |
| 37 | +panic(err) |
| 38 | +} |
| 39 | +// iterate all json objects from child ndoes. |
| 40 | +for _, n := range doc.ChildNodes() { |
| 41 | +fmt.Printf("%s: %v[%T]\n", n.Data, n.Value(), n.Value()) |
| 42 | +} |
| 43 | +// xpath query |
| 44 | +n := jsonquery.FindOne(doc, "//age") |
| 45 | +fmt.Printf("age: %.2f", n.Value().(float64)) |
| 46 | +// select a child node with `age`. = jsonquery.FindOne(doc,"age") |
| 47 | +m := doc.SelectElement("age") |
28 | 48 | ```
|
29 |
| -go get .com/antchfx/jsonquery |
| 49 | + |
| 50 | +// Output: |
| 51 | + |
30 | 52 | ```
|
| 53 | +name: John[string] |
| 54 | +age: 31[float64] |
| 55 | +female: false[bool] |
| 56 | +city: <nil>[<nil>] |
| 57 | +``` |
| 58 | + |
| 59 | +The default Json types and Go types are: |
31 | 60 |
|
32 |
| -#### Load JSON document from URL. |
| 61 | +| JSON | jsonquery(go) | |
| 62 | +| ------- | ------------- | |
| 63 | +| object | interface{} | |
| 64 | +| string | string | |
| 65 | +| number | float64 | |
| 66 | +| boolean | bool | |
| 67 | +| array | []interface{} | |
| 68 | +| null | nil | |
| 69 | + |
| 70 | +For more information about JSON & Go see the https://go.dev/blog/json |
| 71 | + |
| 72 | +## Getting Started |
| 73 | + |
| 74 | +#### Load JSON from URL. |
33 | 75 |
|
34 | 76 | ```go
|
35 | 77 | doc, err := jsonquery.LoadURL("http://www.example.com/feed?json")
|
36 | 78 | ```
|
37 | 79 |
|
38 |
| -#### Load JSON document from string. |
| 80 | +#### Load JSON from string. |
39 | 81 |
|
40 | 82 | ```go
|
41 | 83 | s :=`{
|
42 | 84 | "name":"John",
|
43 |
| -"age":31, |
44 |
| -"city":"New York" |
| 85 | +"age":31, |
| 86 | +"city":"New York" |
45 | 87 | }`
|
46 | 88 | doc, err := jsonquery.Parse(strings.NewReader(s))
|
47 | 89 | ```
|
48 | 90 |
|
49 |
| -#### Load JSON document from io.Reader. |
| 91 | +#### Load JSON from io.Reader. |
50 | 92 |
|
51 | 93 | ```go
|
52 | 94 | f, err := os.Open("./books.json")
|
53 | 95 | doc, err := jsonquery.Parse(f)
|
54 | 96 | ```
|
55 | 97 |
|
56 |
| -#### Find authors of all books in the store. |
| 98 | +#### Parse JSON array |
| 99 | + |
| 100 | +```go |
| 101 | +s := `[1,2,3,4,5,6]` |
| 102 | +doc, _ := jsonquery.Parse(strings.NewReader(s)) |
| 103 | +list := jsonquery.Find(doc, "*") |
| 104 | +for _, n := range list { |
| 105 | +fmt.Print(n.Value().(float64)) |
| 106 | +} |
| 107 | +``` |
| 108 | +// Output: `1,2,3,4,5,6` |
| 109 | + |
| 110 | +#### Convert JSON object to XML |
| 111 | +```go |
| 112 | +doc, _ := jsonquery.Parse(strings.NewReader(s)) |
| 113 | +fmt.Println(doc.OutputXML()) |
| 114 | +``` |
| 115 | + |
| 116 | +### Methods |
| 117 | + |
| 118 | +#### FindOne() |
| 119 | + |
57 | 120 | ```go
|
58 |
| -list := jsonquery.Find(doc, "store/book/*/author") |
59 |
| -// or equal to |
60 |
| -list := jsonquery.Find(doc, "//author") |
61 |
| -// or by QueryAll() |
62 |
| -nodes, err := jsonquery.QueryAll(doc, "//a") |
| 121 | +n := jsonquery.FindOne(doc,"//a") |
63 | 122 | ```
|
64 | 123 |
|
65 |
| -#### Find the third book. |
| 124 | +#### Find() |
66 | 125 |
|
67 | 126 | ```go
|
68 |
| -book := jsonquery.Find(doc, "//book/*[3]") |
| 127 | +list := jsonquery.Find(doc,"//a") |
69 | 128 | ```
|
70 | 129 |
|
71 |
| -#### Find the last book. |
| 130 | +#### QuerySelector() |
72 | 131 |
|
73 | 132 | ```go
|
74 |
| -book := jsonquery.Find(doc, "//book/*[last()]") |
| 133 | +n := jsonquery.QuerySelector(doc, xpath.MustCompile("//a")) |
75 | 134 | ```
|
76 | 135 |
|
77 |
| -#### Find all books that have an isbn number. |
| 136 | +#### QuerySelectorAll() |
78 | 137 |
|
79 | 138 | ```go
|
80 |
| -list := jsonquery.Find(doc, "//book/*[isbn]") |
| 139 | +list :=jsonquery.QuerySelectorAll(doc, xpath.MustCompile("//a")) |
81 | 140 | ```
|
82 | 141 |
|
83 |
| -#### Find all books priced less than 10. |
| 142 | +#### Query() |
84 | 143 |
|
85 | 144 | ```go
|
86 |
| -list := jsonquery.Find(doc, "//book/*[price<10]") |
| 145 | +n, err := jsonquery.Query(doc, "*") |
87 | 146 | ```
|
88 | 147 |
|
89 |
| -Examples |
90 |
| -=== |
| 148 | +#### QueryAll() |
91 | 149 |
|
92 | 150 | ```go
|
93 |
| -func main() { |
94 |
| -s := `{ |
95 |
| -"name": "John", |
96 |
| -"age" : 26, |
97 |
| -"address" : { |
98 |
| -"streetAddress": "naist street", |
99 |
| -"city" : "Nara", |
100 |
| -"postalCode" : "630-0192" |
101 |
| -}, |
102 |
| -"phoneNumbers": [ |
103 |
| -{ |
104 |
| -"type" : "iPhone", |
105 |
| -"number": "0123-4567-8888" |
106 |
| -}, |
107 |
| -{ |
108 |
| -"type" : "home", |
109 |
| -"number": "0123-4567-8910" |
110 |
| -} |
111 |
| -] |
112 |
| -}` |
113 |
| -doc, err := jsonquery.Parse(strings.NewReader(s)) |
114 |
| -if err != nil { |
115 |
| -panic(err) |
116 |
| -} |
117 |
| -name := jsonquery.FindOne(doc, "name") |
118 |
| -fmt.Printf("name: %s\n", name.InnerText()) |
119 |
| -var a []string |
120 |
| -for _, n := range jsonquery.Find(doc, "phoneNumbers/*/number") { |
121 |
| -a = append(a, n.InnerText()) |
122 |
| -} |
123 |
| -fmt.Printf("phone number: %s\n", strings.Join(a, ",")) |
124 |
| -if n := jsonquery.FindOne(doc, "address/streetAddress"); n != nil { |
125 |
| -fmt.Printf("address: %s\n", n.InnerText()) |
126 |
| -} |
| 151 | +list, err := jsonquery.QueryAll(doc, "*") |
| 152 | +``` |
| 153 | + |
| 154 | +#### Query() vs FindOne() |
| 155 | + |
| 156 | +- `Query()` will return an error if give xpath query expr is not valid. |
| 157 | + |
| 158 | +- `FindOne` will panic error and interrupt your program if give xpath query expr is not valid. |
| 159 | + |
| 160 | +#### OutputXML() |
| 161 | + |
| 162 | +Convert current JSON object to XML format. |
| 163 | + |
| 164 | +# Examples |
| 165 | + |
| 166 | +```json |
| 167 | +{ |
| 168 | +"store": { |
| 169 | +"book": [ |
| 170 | +{ |
| 171 | +"id": 1, |
| 172 | +"category": "reference", |
| 173 | +"author": "Nigel Rees", |
| 174 | +"title": "Sayings of the Century", |
| 175 | +"price": 8.95 |
| 176 | +}, |
| 177 | +{ |
| 178 | +"id": 2, |
| 179 | +"category": "fiction", |
| 180 | +"author": "Evelyn Waugh", |
| 181 | +"title": "Sword of Honour", |
| 182 | +"price": 12.99 |
| 183 | +}, |
| 184 | +{ |
| 185 | +"id": 3, |
| 186 | +"category": "fiction", |
| 187 | +"author": "Herman Melville", |
| 188 | +"title": "Moby Dick", |
| 189 | +"isbn": "0-553-21311-3", |
| 190 | +"price": 8.99 |
| 191 | +}, |
| 192 | +{ |
| 193 | +"id": 4, |
| 194 | +"category": "fiction", |
| 195 | +"author": "J. R. R. Tolkien", |
| 196 | +"title": "The Lord of the Rings", |
| 197 | +"isbn": "0-395-19395-8", |
| 198 | +"price": 22.99 |
| 199 | +} |
| 200 | +], |
| 201 | +"bicycle": { |
| 202 | +"color": "red", |
| 203 | +"price": 19.95 |
| 204 | +} |
| 205 | +}, |
| 206 | +"expensive": 10 |
127 | 207 | }
|
| 208 | + |
128 | 209 | ```
|
| 210 | + |
| 211 | +#### Tests |
| 212 | + |
| 213 | +| Query | Matched | Native Value Types | Native Values | |
| 214 | +| ------- | -------------| -------- | -------------| |
| 215 | +| `//book` | 1 | []interface{} | `{"book": [{"id":1,... }, {"id":2,... }, {"id":3,... }, {"id":4,... }]}` | |
| 216 | +| `//book/*` | 4 | [map[string]interface{}] |`{"id":1,... }`, `{"id":2,... }`, `{"id":3,... }`, `{"id":4,... }` | |
| 217 | +| `//*[price<12.99]` | 2 | slice, [map[string]interface{}] | `{"id":1,...}`, `{"id":3,...}` | |
| 218 | +| `//book/*/author` | 4 | []string | `{"author": "Nigel Rees"}`, `{"author": "Evelyn Waugh"}`, `{"author": "Herman Melville"}`, `{"author": "J. R. R. Tolkien"}` | |
| 219 | +| `//book/*[last()]` | 1 | map[string]interface {} | `{"id":4,...}` | |
| 220 | +| `//book/*[1]` | 1 | map[string]interface {} | `{"id":1,...}` | |
| 221 | +| `//book/*[2]` | 1 | map[string]interface{} | `{"id":2,...}` | |
| 222 | +| `//*[isbn]` | 2 | [map[string]interface{}] | `{"id":3,"isbn":"0-553-21311-3",...}`,`{"id":4,"isbn":"0-395-19395-8",...}` | |
| 223 | +| `//*[isbn='0-553-21311-3']` | 1 | object, map[string]interface{} | `{"id":3,"isbn":"0-553-21311-3",...}` | |
| 224 | +| `//bicycle` | 1 | object, map[string]interface {} | `{"bicycle":{"color":...,}}` | |
| 225 | +| `//bicycle/color[text()='red']` | 1 | map[string]interface {} | `{"color":"red"}` | |
| 226 | +| `//*/category[contains(.,'refer')]` | 1 | string | `{"category": "reference"}` | |
| 227 | +| `//price[.=22.99]` | 1 | float64 | `{"price": 22.99}` | |
| 228 | +| `//expensive/text()` | 1 | string | `10` | |
| 229 | + |
| 230 | +For more supports XPath feature and function see https://.com/antchfx/xpath |
0 commit comments