-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
README.md. Update about tutorial and test case.
- Loading branch information
Showing
1 changed file
with
170 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,128 +1,230 @@ | ||
jsonquery | ||
==== | ||
# jsonquery | ||
|
||
[![Build Status](https://travis-ci.org/antchfx/jsonquery.svg?branch=master)](https://travis-ci.org/antchfx/jsonquery) | ||
[![Coverage Status](https://coveralls.io/repos/github/antchfx/jsonquery/badge.svg?branch=master)](https://coveralls.io/github/antchfx/jsonquery?branch=master) | ||
[![GoDoc](https://godoc.org/github.com/antchfx/jsonquery?status.svg)](https://godoc.org/github.com/antchfx/jsonquery) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/jsonquery)](https://goreportcard.com/report/github.com/antchfx/jsonquery) | ||
|
||
Overview | ||
=== | ||
|
||
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. | ||
# Overview | ||
|
||
[jsonquery](https://github.com/antchfx/jsonquery) is XPath query package for JSON document depended on [xpath](https://github.com/antchfx/xpath) package, writing in go. | ||
|
||
XPath query for Golang | ||
=== | ||
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. | ||
|
||
- [htmlquery](https://github.com/antchfx/htmlquery) - XPath query package for HTML document | ||
|
||
- [xmlquery](https://github.com/antchfx/xmlquery) - XPath query package for XML document. | ||
|
||
- [jsonquery](https://github.com/antchfx/jsonquery) - XPath query package for JSON document | ||
### Install Package | ||
|
||
``` | ||
go get github.com/antchfx/jsonquery | ||
``` | ||
|
||
Getting Started | ||
=== | ||
## Get Started | ||
|
||
### Install Package | ||
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. | ||
|
||
```go | ||
s := `{ | ||
"name":"John", | ||
"age":31, | ||
"female":false, | ||
"city":null | ||
}` | ||
doc, err := jsonquery.Parse(strings.NewReader(s)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// iterate all json objects from child ndoes. | ||
for _, n := range doc.ChildNodes() { | ||
fmt.Printf("%s: %v[%T]\n", n.Data, n.Value(), n.Value()) | ||
} | ||
// xpath query | ||
n := jsonquery.FindOne(doc, "//age") | ||
fmt.Printf("age: %.2f", n.Value().(float64)) | ||
// select a child node with `age`. = jsonquery.FindOne(doc,"age") | ||
m := doc.SelectElement("age") | ||
``` | ||
go get github.com/antchfx/jsonquery | ||
|
||
// Output: | ||
|
||
``` | ||
name: John[string] | ||
age: 31[float64] | ||
female: false[bool] | ||
city: <nil>[<nil>] | ||
``` | ||
|
||
The default Json types and Go types are: | ||
|
||
#### Load JSON document from URL. | ||
| JSON | jsonquery(go) | | ||
| ------- | ------------- | | ||
| object | interface{} | | ||
| string | string | | ||
| number | float64 | | ||
| boolean | bool | | ||
| array | []interface{} | | ||
| null | nil | | ||
|
||
For more information about JSON & Go see the https://go.dev/blog/json | ||
|
||
## Getting Started | ||
|
||
#### Load JSON from URL. | ||
|
||
```go | ||
doc, err := jsonquery.LoadURL("http://www.example.com/feed?json") | ||
``` | ||
|
||
#### Load JSON document from string. | ||
#### Load JSON from string. | ||
|
||
```go | ||
s :=`{ | ||
"name":"John", | ||
"age":31, | ||
"city":"New York" | ||
"age":31, | ||
"city":"New York" | ||
}` | ||
doc, err := jsonquery.Parse(strings.NewReader(s)) | ||
``` | ||
|
||
#### Load JSON document from io.Reader. | ||
#### Load JSON from io.Reader. | ||
|
||
```go | ||
f, err := os.Open("./books.json") | ||
doc, err := jsonquery.Parse(f) | ||
``` | ||
|
||
#### Find authors of all books in the store. | ||
#### Parse JSON array | ||
|
||
```go | ||
s := `[1,2,3,4,5,6]` | ||
doc, _ := jsonquery.Parse(strings.NewReader(s)) | ||
list := jsonquery.Find(doc, "*") | ||
for _, n := range list { | ||
fmt.Print(n.Value().(float64)) | ||
} | ||
``` | ||
// Output: `1,2,3,4,5,6` | ||
|
||
#### Convert JSON object to XML | ||
```go | ||
doc, _ := jsonquery.Parse(strings.NewReader(s)) | ||
fmt.Println(doc.OutputXML()) | ||
``` | ||
|
||
### Methods | ||
|
||
#### FindOne() | ||
|
||
```go | ||
list := jsonquery.Find(doc, "store/book/*/author") | ||
// or equal to | ||
list := jsonquery.Find(doc, "//author") | ||
// or by QueryAll() | ||
nodes, err := jsonquery.QueryAll(doc, "//a") | ||
n := jsonquery.FindOne(doc,"//a") | ||
``` | ||
|
||
#### Find the third book. | ||
#### Find() | ||
|
||
```go | ||
book := jsonquery.Find(doc, "//book/*[3]") | ||
list := jsonquery.Find(doc,"//a") | ||
``` | ||
|
||
#### Find the last book. | ||
#### QuerySelector() | ||
|
||
```go | ||
book := jsonquery.Find(doc, "//book/*[last()]") | ||
n := jsonquery.QuerySelector(doc, xpath.MustCompile("//a")) | ||
``` | ||
|
||
#### Find all books that have an isbn number. | ||
#### QuerySelectorAll() | ||
|
||
```go | ||
list := jsonquery.Find(doc, "//book/*[isbn]") | ||
list :=jsonquery.QuerySelectorAll(doc, xpath.MustCompile("//a")) | ||
``` | ||
|
||
#### Find all books priced less than 10. | ||
#### Query() | ||
|
||
```go | ||
list := jsonquery.Find(doc, "//book/*[price<10]") | ||
n, err := jsonquery.Query(doc, "*") | ||
``` | ||
|
||
Examples | ||
=== | ||
#### QueryAll() | ||
|
||
```go | ||
func main() { | ||
s := `{ | ||
"name": "John", | ||
"age" : 26, | ||
"address" : { | ||
"streetAddress": "naist street", | ||
"city" : "Nara", | ||
"postalCode" : "630-0192" | ||
}, | ||
"phoneNumbers": [ | ||
{ | ||
"type" : "iPhone", | ||
"number": "0123-4567-8888" | ||
}, | ||
{ | ||
"type" : "home", | ||
"number": "0123-4567-8910" | ||
} | ||
] | ||
}` | ||
doc, err := jsonquery.Parse(strings.NewReader(s)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
name := jsonquery.FindOne(doc, "name") | ||
fmt.Printf("name: %s\n", name.InnerText()) | ||
var a []string | ||
for _, n := range jsonquery.Find(doc, "phoneNumbers/*/number") { | ||
a = append(a, n.InnerText()) | ||
} | ||
fmt.Printf("phone number: %s\n", strings.Join(a, ",")) | ||
if n := jsonquery.FindOne(doc, "address/streetAddress"); n != nil { | ||
fmt.Printf("address: %s\n", n.InnerText()) | ||
} | ||
list, err := jsonquery.QueryAll(doc, "*") | ||
``` | ||
|
||
#### Query() vs FindOne() | ||
|
||
- `Query()` will return an error if give xpath query expr is not valid. | ||
|
||
- `FindOne` will panic error and interrupt your program if give xpath query expr is not valid. | ||
|
||
#### OutputXML() | ||
|
||
Convert current JSON object to XML format. | ||
|
||
# Examples | ||
|
||
```json | ||
{ | ||
"store": { | ||
"book": [ | ||
{ | ||
"id": 1, | ||
"category": "reference", | ||
"author": "Nigel Rees", | ||
"title": "Sayings of the Century", | ||
"price": 8.95 | ||
}, | ||
{ | ||
"id": 2, | ||
"category": "fiction", | ||
"author": "Evelyn Waugh", | ||
"title": "Sword of Honour", | ||
"price": 12.99 | ||
}, | ||
{ | ||
"id": 3, | ||
"category": "fiction", | ||
"author": "Herman Melville", | ||
"title": "Moby Dick", | ||
"isbn": "0-553-21311-3", | ||
"price": 8.99 | ||
}, | ||
{ | ||
"id": 4, | ||
"category": "fiction", | ||
"author": "J. R. R. Tolkien", | ||
"title": "The Lord of the Rings", | ||
"isbn": "0-395-19395-8", | ||
"price": 22.99 | ||
} | ||
], | ||
"bicycle": { | ||
"color": "red", | ||
"price": 19.95 | ||
} | ||
}, | ||
"expensive": 10 | ||
} | ||
|
||
``` | ||
|
||
#### Tests | ||
|
||
| Query | Matched | Native Value Types | Native Values | | ||
| ------- | -------------| -------- | -------------| | ||
| `//book` | 1 | []interface{} | `{"book": [{"id":1,... }, {"id":2,... }, {"id":3,... }, {"id":4,... }]}` | | ||
| `//book/*` | 4 | [map[string]interface{}] |`{"id":1,... }`, `{"id":2,... }`, `{"id":3,... }`, `{"id":4,... }` | | ||
| `//*[price<12.99]` | 2 | slice, [map[string]interface{}] | `{"id":1,...}`, `{"id":3,...}` | | ||
| `//book/*/author` | 4 | []string | `{"author": "Nigel Rees"}`, `{"author": "Evelyn Waugh"}`, `{"author": "Herman Melville"}`, `{"author": "J. R. R. Tolkien"}` | | ||
| `//book/*[last()]` | 1 | map[string]interface {} | `{"id":4,...}` | | ||
| `//book/*[1]` | 1 | map[string]interface {} | `{"id":1,...}` | | ||
| `//book/*[2]` | 1 | map[string]interface{} | `{"id":2,...}` | | ||
| `//*[isbn]` | 2 | [map[string]interface{}] | `{"id":3,"isbn":"0-553-21311-3",...}`,`{"id":4,"isbn":"0-395-19395-8",...}` | | ||
| `//*[isbn='0-553-21311-3']` | 1 | object, map[string]interface{} | `{"id":3,"isbn":"0-553-21311-3",...}` | | ||
| `//bicycle` | 1 | object, map[string]interface {} | `{"bicycle":{"color":...,}}` | | ||
| `//bicycle/color[text()='red']` | 1 | map[string]interface {} | `{"color":"red"}` | | ||
| `//*/category[contains(.,'refer')]` | 1 | string | `{"category": "reference"}` | | ||
| `//price[.=22.99]` | 1 | float64 | `{"price": 22.99}` | | ||
| `//expensive/text()` | 1 | string | `10` | | ||
|
||
For more supports XPath feature and function see https://github.com/antchfx/xpath |