how do you traverse a json file using go-simplejson

huangapple go评论89阅读模式
英文:

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)
    }
}

play

注意:

  • 你的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)
	}
}

<kbd>play</kbd>

Notes:

  • Your json example is wrong, &quot;key10&quot;, &quot;val10&quot; should be &quot;key10&quot;: &quot;val10&quot;.
  • When you're in doubt of how a data structure looks and too lazy to read the code, use fmt.Printf(&quot;%#v&quot;, 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 (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
)

type Document struct {
	Data DataStruct
}

type DataStruct struct {
	Docs []interface{}
}

func main() {
	doc, err := ioutil.ReadFile(&quot;./doc.json&quot;)
	if err != nil {
		panic(err)
	}
	var document Document
	err = json.Unmarshal(doc, &amp;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(&quot;file%d.json&quot;, index), b, 0777)
		if err != nil {
			panic(err)
		}
		fmt.Println(string(b))
	}
}

The sample code will provide you two files with contents like this:

{&quot;key00&quot;:&quot;val00&quot;,&quot;key01&quot;:&quot;val01&quot;}

and

{&quot;key10&quot;:&quot;val10&quot;,&quot;key11&quot;:&quot;val11&quot;}

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.

huangapple
  • 本文由 发表于 2015年2月21日 16:47:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/28643877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定