英文:
how do you traverse a json file using go-simplejson
问题
我有一个形式为JSON的文件:
{
"data": {
"docs": [
{"key00": "val00", "key01": "val01"},
{"key10": "val10", "key11": "val11"}
]
}
}
我想将其转换为单独的JSON文档:
file0.json
{
{"key00": "val00", "key01": "val01"}
}
file1.json
{
{"key10": "val10", "key11": "val11"}
}
我可以使用以下代码枚举数组内容:
j, _ := ioutil.ReadFile(path)
dec, _ := simplejson.NewFromReader(bytes.NewReader(j))
for i,v := range dec.Get("data").Get("docs").MustArray() {
out := simplejson.New()
/* ??? 将dec的键/值对移动到out ??? */
b, _ := out.EncodePretty()
ioutil.WriteFile(outpath, b, 0777)
}
但是我不确定如何迭代数组条目中的键/值对。这是一个简洁的库,但似乎没有很多示例,而且我目前对golang的专业知识有限。
任何帮助将不胜感激..谢谢!
英文:
I have a JSON file of the form:
{
"data": {
"docs": [
{"key00": "val00", "key01": "val01"},
{"key10": "val10", "key11": "val11"}
]
}
}
and I would like to convert it to separate JSON docs:
file0.json
{
{"key00": "val00", "key01": "val01"}
}
file1.json
{
{"key10": "val10", "key11": "val11"}
}
I can enumerate over the array contents using:
j, _ := ioutil.ReadFile(path)
dec, _ := simplejson.NewFromReader(bytes.NewReader(j))
for i,v := range dec.Get("data").Get("docs").MustArray() {
out := simplejson.New()
/* ??? move dec key/value pairs to out ??? */
b, _ := out.EncodePretty()
ioutil.WriteFile(outpath, b, 0777)
}
but I'm not sure how to iterate over the key/value pairs within the array entries. It's a nice, succinct library but there don't appear to be a lot of examples and my golang expertise is currently limited.
Any help would be appreciated.. thanks!
答案1
得分: 2
你可以使用simplejson.Set
:
for _, doc := range dec.Get("data").Get("docs").MustArray() {
out := simplejson.New()
// doc是一个持有map的interface{},我们需要进行类型断言
for k, v := range doc.(map[string]interface{}) {
out.Set(k, v)
}
b, _ := out.EncodePretty()
fmt.Printf("%s\n", b)
}
然而,在这种情况下,simplejson可能有些过于复杂,使用结构体和标准库会更高效。
为了完整起见,这是使用标准库的版本:
type DataLayout struct {
Data struct {
Docs []map[string]string `json:"docs"`
} `json:"data"`
}
func main() {
var in DataLayout
err := json.NewDecoder(strings.NewReader(j)).Decode(&in)
if err != nil {
log.Fatal(err)
}
for _, doc := range in.Data.Docs {
b, err := json.MarshalIndent(doc, "", "\t")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", b)
}
}
注意:
- 你的JSON示例有误,
"key10", "val10"
应该是"key10": "val10"
。 - 当你对数据结构不确定并且懒得阅读代码时,可以使用
fmt.Printf("%#v", doc)
来查看其结构。
英文:
You can use simplejson.Set
:
for _, doc := range dec.Get("data").Get("docs").MustArray() {
out := simplejson.New()
// doc is an interface{} holding a map, we have to type assert it.
for k, v := range doc.(map[string]interface{}) {
out.Set(k, v)
}
b, _ := out.EncodePretty()
fmt.Printf("%s\n", b)
}
However in that instance, simplejson is an overkill and using a struct / stdlib is more efficient.
For completeness sake, the std lib version:
type DataLayout struct {
Data struct {
Docs []map[string]string `json:"docs"`
} `json:"data"`
}
func main() {
var in DataLayout
err := json.NewDecoder(strings.NewReader(j)).Decode(&in)
if err != nil {
log.Fatal(err)
}
for _, doc := range in.Data.Docs {
b, err := json.MarshalIndent(doc, "", "\t")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", b)
}
}
Notes:
- Your json example is wrong,
"key10", "val10"
should be"key10": "val10"
. - When you're in doubt of how a data structure looks and too lazy to read the code, use
fmt.Printf("%#v", doc)
to see how it looks like.
答案2
得分: 1
有使用simplejson的特定原因吗?很多编码可以使用标准的JSON库来完成。
使用标准库,你可以像这样解决你的问题:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type Document struct {
Data DataStruct
}
type DataStruct struct {
Docs []interface{}
}
func main() {
doc, err := ioutil.ReadFile("./doc.json")
if err != nil {
panic(err)
}
var document Document
err = json.Unmarshal(doc, &document)
if err != nil {
panic(err)
}
for index := range document.Data.Docs {
b, err := json.Marshal(document.Data.Docs[index])
if err != nil {
panic(err)
}
err = ioutil.WriteFile(fmt.Sprintf("file%d.json", index), b, 0777)
if err != nil {
panic(err)
}
fmt.Println(string(b))
}
}
这个示例代码将为你提供两个文件,内容如下:
{"key00":"val00","key01":"val01"}
和
{"key10":"val10","key11":"val11"}
然而,如果你注意到我在DataStruct中使用了[]interface{}的表示法,一般来说这被认为是不好的做法。如果你的真实数据有任何类型声明,你应该创建一个新的结构体来表示。
英文:
Is there any specific reason to use simplejson? A lot of encoding can be done with the standard JSON library.
Using the standard library you could solve your problem like this:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type Document struct {
Data DataStruct
}
type DataStruct struct {
Docs []interface{}
}
func main() {
doc, err := ioutil.ReadFile("./doc.json")
if err != nil {
panic(err)
}
var document Document
err = json.Unmarshal(doc, &document)
if err != nil {
panic(err)
}
for index := range document.Data.Docs {
b, err := json.Marshal(document.Data.Docs[index])
if err != nil {
panic(err)
}
err = ioutil.WriteFile(fmt.Sprintf("file%d.json", index), b, 0777)
if err != nil {
panic(err)
}
fmt.Println(string(b))
}
}
The sample code will provide you two files with contents like this:
{"key00":"val00","key01":"val01"}
and
{"key10":"val10","key11":"val11"}
However, if you noticed I used the []interface{} notation in the DataStruct, which in general is considered bad practice. You should create a new structure with proper type declarations if your real-world data has any.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论