how do you traverse a json file using go-simplejson

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

how do you traverse a json file using go-simplejson

问题

我有一个形式为JSON的文件:

  1. {
  2. "data": {
  3. "docs": [
  4. {"key00": "val00", "key01": "val01"},
  5. {"key10": "val10", "key11": "val11"}
  6. ]
  7. }
  8. }

我想将其转换为单独的JSON文档:
file0.json

  1. {
  2. {"key00": "val00", "key01": "val01"}
  3. }

file1.json

  1. {
  2. {"key10": "val10", "key11": "val11"}
  3. }

我可以使用以下代码枚举数组内容:

  1. j, _ := ioutil.ReadFile(path)
  2. dec, _ := simplejson.NewFromReader(bytes.NewReader(j))
  3. for i,v := range dec.Get("data").Get("docs").MustArray() {
  4. out := simplejson.New()
  5. /* ??? 将dec的键/值对移动到out ??? */
  6. b, _ := out.EncodePretty()
  7. ioutil.WriteFile(outpath, b, 0777)
  8. }

但是我不确定如何迭代数组条目中的键/值对。这是一个简洁的库,但似乎没有很多示例,而且我目前对golang的专业知识有限。

任何帮助将不胜感激..谢谢!

英文:

I have a JSON file of the form:

  1. {
  2. "data": {
  3. "docs": [
  4. {"key00": "val00", "key01": "val01"},
  5. {"key10": "val10", "key11": "val11"}
  6. ]
  7. }
  8. }

and I would like to convert it to separate JSON docs:
file0.json

  1. {
  2. {"key00": "val00", "key01": "val01"}
  3. }

file1.json

  1. {
  2. {"key10": "val10", "key11": "val11"}
  3. }

I can enumerate over the array contents using:

  1. j, _ := ioutil.ReadFile(path)
  2. dec, _ := simplejson.NewFromReader(bytes.NewReader(j))
  3. for i,v := range dec.Get("data").Get("docs").MustArray() {
  4. out := simplejson.New()
  5. /* ??? move dec key/value pairs to out ??? */
  6. b, _ := out.EncodePretty()
  7. ioutil.WriteFile(outpath, b, 0777)
  8. }

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

  1. for _, doc := range dec.Get("data").Get("docs").MustArray() {
  2. out := simplejson.New()
  3. // doc是一个持有map的interface{},我们需要进行类型断言
  4. for k, v := range doc.(map[string]interface{}) {
  5. out.Set(k, v)
  6. }
  7. b, _ := out.EncodePretty()
  8. fmt.Printf("%s\n", b)
  9. }

然而,在这种情况下,simplejson可能有些过于复杂,使用结构体和标准库会更高效。

为了完整起见,这是使用标准库的版本:

  1. type DataLayout struct {
  2. Data struct {
  3. Docs []map[string]string `json:"docs"`
  4. } `json:"data"`
  5. }
  6. func main() {
  7. var in DataLayout
  8. err := json.NewDecoder(strings.NewReader(j)).Decode(&in)
  9. if err != nil {
  10. log.Fatal(err)
  11. }
  12. for _, doc := range in.Data.Docs {
  13. b, err := json.MarshalIndent(doc, "", "\t")
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. fmt.Printf("%s\n", b)
  18. }
  19. }

play

注意:

  • 你的JSON示例有误,"key10", "val10" 应该是 "key10": "val10"
  • 当你对数据结构不确定并且懒得阅读代码时,可以使用 fmt.Printf("%#v", doc) 来查看其结构。
英文:

You can use simplejson.Set:

  1. for _, doc := range dec.Get("data").Get("docs").MustArray() {
  2. out := simplejson.New()
  3. // doc is an interface{} holding a map, we have to type assert it.
  4. for k, v := range doc.(map[string]interface{}) {
  5. out.Set(k, v)
  6. }
  7. b, _ := out.EncodePretty()
  8. fmt.Printf("%s\n", b)
  9. }

However in that instance, simplejson is an overkill and using a struct / stdlib is more efficient.

For completeness sake, the std lib version:

  1. type DataLayout struct {
  2. Data struct {
  3. Docs []map[string]string `json:"docs"`
  4. } `json:"data"`
  5. }
  6. func main() {
  7. var in DataLayout
  8. err := json.NewDecoder(strings.NewReader(j)).Decode(&in)
  9. if err != nil {
  10. log.Fatal(err)
  11. }
  12. for _, doc := range in.Data.Docs {
  13. b, err := json.MarshalIndent(doc, "", "\t")
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. fmt.Printf("%s\n", b)
  18. }
  19. }

<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库来完成。

使用标准库,你可以像这样解决你的问题:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. )
  7. type Document struct {
  8. Data DataStruct
  9. }
  10. type DataStruct struct {
  11. Docs []interface{}
  12. }
  13. func main() {
  14. doc, err := ioutil.ReadFile("./doc.json")
  15. if err != nil {
  16. panic(err)
  17. }
  18. var document Document
  19. err = json.Unmarshal(doc, &document)
  20. if err != nil {
  21. panic(err)
  22. }
  23. for index := range document.Data.Docs {
  24. b, err := json.Marshal(document.Data.Docs[index])
  25. if err != nil {
  26. panic(err)
  27. }
  28. err = ioutil.WriteFile(fmt.Sprintf("file%d.json", index), b, 0777)
  29. if err != nil {
  30. panic(err)
  31. }
  32. fmt.Println(string(b))
  33. }
  34. }

这个示例代码将为你提供两个文件,内容如下:

  1. {"key00":"val00","key01":"val01"}

  1. {"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:

  1. package main
  2. import (
  3. &quot;encoding/json&quot;
  4. &quot;fmt&quot;
  5. &quot;io/ioutil&quot;
  6. )
  7. type Document struct {
  8. Data DataStruct
  9. }
  10. type DataStruct struct {
  11. Docs []interface{}
  12. }
  13. func main() {
  14. doc, err := ioutil.ReadFile(&quot;./doc.json&quot;)
  15. if err != nil {
  16. panic(err)
  17. }
  18. var document Document
  19. err = json.Unmarshal(doc, &amp;document)
  20. if err != nil {
  21. panic(err)
  22. }
  23. for index := range document.Data.Docs {
  24. b, err := json.Marshal(document.Data.Docs[index])
  25. if err != nil {
  26. panic(err)
  27. }
  28. err = ioutil.WriteFile(fmt.Sprintf(&quot;file%d.json&quot;, index), b, 0777)
  29. if err != nil {
  30. panic(err)
  31. }
  32. fmt.Println(string(b))
  33. }
  34. }

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

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

and

  1. {&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:

确定