# #arrays #json #go #unmarshalling
Вопрос:
какова наилучшая практика для удаления определенной части большого JSON со статическими именами свойств в GO?
моя карта JSON выглядит так
{
"top_view" : {
"@self" : "https://generic.com",
"graph" : {
"nodes" : [ { } ],
"relations" : [ { } ]
},
"view_status" : {}
}
}
и мне нужно только получить массив узлов
Вот что я получил до сих пор,
https://play.golang.org/p/btfRojEGqUu
Я знаю только, как разархивировать часть узлов, но я не знаю, как сказать Go, чтобы начать разархивировать только этот объект, поэтому код не будет работать, если я скормлю все дерево JSON. Пожалуйста, посоветуйте, спасибо!
Комментарии:
1. Я не думаю, что это было бы возможно, так как дерево должно быть проанализировано сверху вниз. Однако вы можете поступить наоборот, т. е. сохранить
nodes
ключи в порядке2. Объявите типы Go с минимальной структурой, необходимой для получения нужной вам детали. Разархивируйте документ JSON и выберите нужную часть.
var data = struct { TopView struct { Self struct { Graph Graph } `json:"@self"` } `json:"top_view"` }
3. На мой взгляд, лучший способ-это просто разархивировать соответствующую структуру, а затем игнорировать нежелательные части. Например: play.golang.org/p/y_9IdVpZdqW
Ответ №1:
Это один из способов сделать это: определите структуру, которая показывает путь к узлу. Вы можете пропустить элементы в JSON, которые вам не интересны. Например:
type Whole struct {
TopView struct {
Self string `json:"@self"`
Graph struct {
Nodes []Node `json:"nodes"`
} `json:"graph"`
} `json:"top_view"`
}
Затем маршалируйте узел
var whole Whole
err := json.Unmarshal([]byte(jsonResp), amp;whole)
Вот рабочий код :
https://play.golang.org/p/5WvPocce_vh
Комментарии:
1. спасибо, мне очень понравилось это элегантное решение!
Ответ №2:
Вы можете удалить все данные JSON без какого-либо конкретного типа, определенного в go
коде. Использование type assertion
и type switch
детализация данных, просто не обработанных.
Ниже приведен рабочий пример вашей проблемы с использованием вышеупомянутых концепций. Возможно, вам потребуется дополнительно уточнить эту основу ваших требований, но основная концепция остается прежней:
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
jsonResponse := `{
"top_view" : {
"@self" : "https://generic.com",
"graph" : {
"nodes" : [ {
"@self" : "https://generic.com:443",
"id" : "1;;45d554600be28ee49c99d26e536225ea;;461ff354437881f6b5973d4af366b91c;;4c0f2cc8e29a4fe09240b2a0c311508d",
"ci" : {
"id" : "4c0f2cc8e29a4fe09240b2a0c311508d",
"name" : "NOICE",
"type" : "ci_collection",
"type_label" : "CiCollection",
"icon" : "/logical_group_32.svg"
},
"has_children" : true
}, {
"@self" : "https://generic.com:443hjkhk",
"id" : "1;;45d554600be28ee49c99d26e536225ea;;4e22910a478bf6939aed36fef22dc79e;;4a7788eeecbbeee3a8bb3189ba67f269",
"ci" : {
"id" : "4a7788eeecbbeee3a8bb3189ba67f269",
"name" : "NOTNOICE",
"type" : "ci_collection",
"type_label" : "CiCollection",
"icon" : "/logical_group_32.svg"
},
"has_children" : true
}, {
"@self" : "https://generic.com:443/fghfgh",
"id" : "1;;45d554600be28ee49c99d26e536225ea;;461ff354437881f6b5973d4af366b91c;;4c0f2cc8e29a4fe09240b2a0c311508d;;40b8b314821d01ac874f7209c228ab8f",
"ci" : {
"id" : "40b8b314821d01ac874f7209c228ab8f",
"name" : "NOICE",
"type" : "ci_collection",
"type_label" : "CiCollection",
"icon" : "/logical_group_32.svg"
},
"has_children" : true
}, {
"@self" : "https://generic.com:443/gfhgh",
"id" : "1;;45d554600be28ee49c99d26e536225ea;;4a208e0deee006668bb3cfab6541a869;;4bd30d48bc1c81b398e17435ba519f2d;;4a1c671cefd3b5b9931b4312382ff2e4",
"ci" : {
"id" : "4a1c671cefd3b5b9931b4312382ff2e4",
"name" : "AAA",
"type" : "ci_collection",
"type_label" : "CiCollection",
"icon" : "/logical_group_32.svg"
},
"has_children" : true
} ],
"relations" : [ { } ]
},
"view_status" : {}
}
}`
var res interface{}
err := json.Unmarshal([]byte(jsonResponse), amp;res)
if err != nil {
log.Fatal(err)
}
parseArbitoryJSONObject(res)
}
func parseArbitoryJSONObject(jsonObject interface{}) {
data := jsonObject.(map[string]interface{})
for k, v := range data {
switch val := v.(type) {
case string:
fmt.Println(k, "is string:", val)
case float64:
fmt.Println(k, "is float64", val)
case bool:
fmt.Println(k, "is boolean", val)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range val {
fmt.Println(i, u)
}
case map[string]interface{}:
fmt.Println(k, "is an map[string]interface{}:")
parseArbitoryJSONObject(val)
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
}
Здесь json.Unmarshal
используется empty interface
то, что может содержать любое значение. И функция parseArbitoryJSONObject()
используется type assertion
для облегчения извлечения значений из незафиксированных данных.
Это то type switch
место, где вам, возможно, потребуется дополнительно поместить или изменить логику, чтобы получить нужный элемент из незафиксированного объекта JSON.
ниже приведена ссылка на фрагмент кода go-playground для вашей справки: