Введение
Каждый разработчик, будь то фронтенд или бэкенд, регулярно использует JSON в своей повседневной работе. JSON — это очень простой формат обмена данными. По сравнению с XML он более гибкий, легкий и простой в использовании. JSON тожеRESTful APIРекомендуемый формат. Иногда нам нужно прочитать только определенные поля в JSON. Если вы вручную разбираете и читаете слой за слоем, это становится чрезвычайно громоздким. Особенно если уровень вложенности очень глубокий. Сегодня мы представляемgojsonq
. Это может помочь нам очень удобно манипулировать JSON.
быстрый в использовании
Сначала установите:
$ go get github.com/thedevsaddam/gojsonq
После использования:
package main
import (
"fmt"
"github.com/thedevsaddam/gojsonq"
)
func main() {
content := `{
"user": {
"name": "dj",
"age": 18,
"address": {
"provice": "shanghai",
"district": "xuhui"
},
"hobbies":["chess", "programming", "game"]
}
}`
gq := gojsonq.New().FromString(content)
district := gq.Find("user.address.district")
fmt.Println(district)
gq.Reset()
hobby := gq.Find("user.hobbies.[0]")
fmt.Println(hobby)
}
Операция очень проста:
- первый звонок
gojsonq.New()
СоздаватьJSONQ
Объект; - Затем вы можете использовать методы этого типа для запроса свойств.
В приведенном выше коде мы напрямую читаем самый внутреннийdistrict
ценность иhobbies
Первый элемент массива! между слоями.
разделены, если это массив, передать после поля атрибута.[index]
читать нижний индекс какindex
Элементы. Этот метод может обеспечить очень гибкое чтение.
Обратите внимание на деталь: после запроса мы вручную вызываем один разReset()
метод. так какJSONQ
объект звонитFind
метод, текущий узел будет записан во внутреннюю память, и следующий запрос начнется с последнего искомого узла. То есть, если мы закомментируемjq.Reset()
,секундаFind()
Метод фактически ищетuser.address.district.user.hobbies.[0]
, естественно возвратnil
. Кроме,gojsonq
Предусмотрен и другой способ. Если вы хотите сохранить некоторую информацию о состоянии текущего запроса, вы можете вызватьJSONQ
изCopy
Метод возвращает объект в его начальном состоянии, который будет совместно использовать базовую строку JSON и проанализированный объект. вышеgq.Reset()
Его можно заменить следующей строкой кода:
gpCopy := gp.Copy()
можно использовать позжеgpCopy
Запросhobbies
.
этоgojsonq
Особенность библиотеки, но она тоже доставляет много хлопот новичкам и требует особого внимания. По факту,JSONQ
Многие из предоставленных методов изменяют текущий узел, как мы увидим более четко в следующем разделе.
источник данных
Помимо загрузки из строки,jsonq
Также разрешает файлы иio.Reader
читать содержимое. использовать отдельноJSONQ
объектFile
иReader
метод:
func main() {
gq := gojsonq.New().File("./data.json")
fmt.Println(gq.Find("items.[1].price"))
}
Эффект такой же, как и у следующей программы:
func main() {
file, err := os.OpenFile("./data.json", os.O_RDONLY, 0666)
if err != nil {
log.Fatal(err)
}
gq := gojsonq.New().Reader(file)
fmt.Println(gq.Find("items.[1].price"))
}
Для удобства последующей демонстрации я построилdata.json
документ:
{
"name": "shopping cart",
"description": "List of items in your cart",
"prices": ["2400", "2100", "1200", "400.87", "89.90", "150.10"],
"items": [
{
"id": 1,
"name": "Apple",
"count": 2,
"price": 12
},
{
"id": 2,
"name": "Notebook",
"count": 10,
"price": 3
},
{
"id": 3,
"name": "Pencil",
"count": 5,
"price": 1
},
{
"id": 4,
"name": "Camera",
"count": 1,
"price": 1750
},
{
"id": null,
"name": "Invalid Item",
"count": 1,
"price": 12000
}
]
}
Расширенный поиск
gojsonq
Уникальность его в том, что он может выполнять условные запросы, такие как SQL, вы можете выбирать, какие поля возвращать, и вы можете делать некоторую агрегированную статистику.
Отображение полей
Иногда нам нужны только несколько полей в объекте, тогда мы можем использоватьSelect
Укажите, какие поля возвращаются, а остальные нет:
func main() {
r := gojsonq.New().File("./data.json").From("items").Select("id", "name").Get()
data, _ := json.MarshalIndent(r, "", " ")
fmt.Println(string(data))
}
будет выводить толькоid
иname
Поле:
$ go run main.go
[
{
"id": 1,
"name": "Apple"
},
{
"id": 2,
"name": "Notebook"
},
{
"id": 3,
"name": "Pencil"
},
{
"id": 4,
"name": "Camera"
},
{
"id": null,
"name": "Invalid Item"
}
]
Чтобы отобразить немного более интуитивно понятным, я используюjson.MarshalIndent()
Сделал некоторые украшения на выходе.
Это похоже на SQL?Select id,name From items
...
Вот введениеFrom
метод, функция этого метода состоит в том, чтобы переместить текущий узел в указанную позицию. Выше также упоминалось, что записывается положение текущего узла. Например, в приведенном выше коде мы сначала перемещаем текущий узел вitems
, все последующие запросы и операции агрегирования выполняются для этого массива. ФактическиFind
метод вызывается внутриFrom
:
// src/github.com/thedevsaddam/gojsonq/jsonq.go
func (j *JSONQ) Find(path string) interface{} {
return j.From(path).Get()
}
func (j *JSONQ) From(node string) *JSONQ {
j.node = node
v, err := getNestedValue(j.jsonContent, node, j.option.separator)
if err != nil {
j.addError(err)
}
// ============= 注意这一行,记住当前节点位置
j.jsonContent = v
return j
}
Наконец, вы должны позвонитьGet()
, который объединяет все условия и выполняет запрос, возвращая результат.
Условный запрос
имеютSelect
иFrom
, как не могWhere
Шерстяная ткань?gojsonq
который предоставилWhere
Есть много методов, и мы, вероятно, рассмотрим только некоторые из них.
прежде всего,Where(key, op, val)
, это общийWhere
состояние, выражающееkey
иval
Это удовлетвореноop
связь.op
Встроенных около 20, а также поддерживается настройка. Например=
значит равный,!=
значит не ждать,startsWith
выражатьval
так или иначеkey
префиксы полей и т.д.;
Многие другие условия являютсяWhere
особые случаи, такие какWhereIn(key, val)
эквивалентноWhere(key, "in", val)
,WhereStartsWith(key, val)
эквивалентноWhere(key, "startsWith", val)
.
по умолчанию,Where
условияAnd
подключено, мы можем пройтиOrWhere
будь как будетOr
соединять:
func main() {
gq := gojsonq.New().File("./data.json")
r := gq.From("items").Select("id", "name").
Where("id", "=", 1).OrWhere("id", "=", 2).Get()
fmt.Println(r)
gq.Reset()
r = gq.From("items").Select("id", "name", "count").
Where("count", ">", 1).Where("price", "<", 100).Get()
fmt.Println(r)
}
Первый запрос выше находитid
1или2 записи. Второй запрос, найтиcount
Больше 1и price
Менее 100 записей.
Укажите смещение и количество возвращаемых записей
Иногда мы хотим разбить на страницы и вернуть первые 3 записи по первому запросу и следующие 3 записи по второму запросу. мы можем использоватьJSONQ
объектOffset
иLimit
метод, чтобы указать смещение и количество возвращаемых записей:
func main() {
gq := gojsonq.New().File("./data.json")
r1 := gq.From("items").Select("id", "name").Offset(0).Limit(3).Get()
fmt.Println("First Page:", r1)
gq.Reset()
r2 := gq.From("items").Select("id", "name").Offset(3).Limit(3).Get()
fmt.Println("Second Page:", r2)
}
Посмотрим на результат работы:
$ go run main.go
First Page: [map[id:1 name:Apple] map[id:2 name:Notebook] map[id:3 name:Pencil]]
Second Page: [map[id:4 name:Camera] map[id:<nil> name:Invalid Item]]
Сводная статистика
Мы также можем сделать простую статистику по некоторым полям, вычислить сумму, среднее значение, максимум, минимум и т. д.:
func main() {
gq := gojsonq.New().File("./data.json").From("items")
fmt.Println("Total Count:", gq.Sum("count"))
fmt.Println("Min Price:", gq.Min("price"))
fmt.Println("Max Price:", gq.Max("price"))
fmt.Println("Avg Price:", gq.Avg("price"))
}
Выше подсчитывается общее количество, минимальная цена, максимальная цена и средняя цена товара.
Ни один из методов класса агрегированной статистики не изменит указатель текущего узла, поэтомуJSONQ
Объекты можно использовать повторно!
Данные также можно группировать и сортировать:
func main() {
gq := gojsonq.New().File("./data.json")
fmt.Println(gq.From("items").GroupBy("price").Get())
gq.Reset()
fmt.Println(gq.From("items").SortBy("price", "desc").Get())
}
Другие форматы
по умолчанию,gojsonq
Разбирать данные в формате JSON. Мы также можем установить другие парсеры форматов, чтобыgojsonq
Другие форматы данных могут быть обработаны:
func main() {
jq := gojsonq.New(gojsonq.SetDecoder(&yamlDecoder{})).File("./data.yaml")
jq.From("items").Where("price", "<=", 500)
fmt.Printf("%v\n", jq.First())
}
type yamlDecoder struct {
}
func (i *yamlDecoder) Decode(data []byte, v interface{}) error {
bb, err := yaml.YAMLToJSON(data)
if err != nil {
return err
}
return json.Unmarshal(bb, &v)
}
Приведенный выше код используетсяyaml
Библиотеки, требующие дополнительной установки:
$ go get github.com/ghodss/yaml
Парсеру нужно только реализоватьgojsonq.Decoder
интерфейс, может быть установлен какgojsonq
, так что любой формат может быть обработан:
// src/github.com/thedevsaddam/gojsonq/decoder.go
type Decoder interface {
Decode(data []byte, v interface{}) error
}
Суммировать
gojsonq
Есть также расширенные функции, такие как настройкаWhere
Тип операции , принимает первое, последнее, N-е значение и т. д. Если вам интересно, вы можете провести собственное исследование~
Если вы найдете забавную и простую в использовании языковую библиотеку Go, вы можете отправить сообщение о проблеме в ежедневной библиотеке Go GitHub😄
Ссылаться на
- gojsonq GitHub:GitHub.com/the vs AD хит…
- Перейти на ежедневный репозиторий GitHub:GitHub.com/Darenjun/go-of…
я
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat [GoUpUp], учитесь вместе и добивайтесь прогресса вместе ~
Эта статья опубликована в блогеOpenWriteвыпуск!