【问题标题】:Parsing multiple JSON objects in Go在 Go 中解析多个 JSON 对象
【发布时间】:2021-11-09 21:06:56
【问题描述】:

使用encoding/json 包可以很容易地解析像下面这样的对象。

[ 
    {"something":"foo"},
    {"something-else":"bar"}
]

我面临的问题是当服务器返回多个字典时:

{"something":"foo"}
{"something-else":"bar"}

无法使用下面的代码解析。

correct_format := strings.Replace(string(resp_body), "}{", "},{", -1)
json_output := "[" + correct_format + "]"

我正在尝试解析 Common Crawl 数据(请参阅 example)。

我该怎么做?

【问题讨论】:

  • 它不是一个有效的 json 这就是首先将它转换成有效的 json 然后解析它的原因。
  • 那个JSON根本无法解析,更别说轻易解析了,因为它是无效的。
  • Json 不是无效的。每行实际上包含一个单独的 Json 对象。
  • 请注意,问题中 URL 处的文档包含一个带有 line-delimited JSON 的文本文件(即每行一个 JSON 文档)。
  • 对不起,我错误地发布了错误的json

标签: json go


【解决方案1】:

假设您的输入确实是一系列有效的 JSON 文档,请使用 json.Decoder 对其进行解码:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

var input = `
{"foo": "bar"}
{"foo": "baz"}
`

type Doc struct {
    Foo string
}

func main() {
    dec := json.NewDecoder(strings.NewReader(input))
    for {
        var doc Doc

        err := dec.Decode(&doc)
        if err == io.EOF {
            // all done
            break
        }
        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("%+v\n", doc)
    }
}

游乐场:https://play.golang.org/p/ANx8MoMC0yq

如果您的输入确实是您在问题中显示的内容,那不是 JSON,您必须编写自己的解析器。

【讨论】:

    【解决方案2】:

    似乎每一行都是它自己的 json 对象。

    您可以使用以下代码将这个输出构造成正确的 json:

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        base := `{"trolo":"lolo"}
    {"trolo2":"lolo2"}`
    
        delimited := strings.Replace(base, "\n", ",", -1)
    
        final := "[" + delimited + "]"
        fmt.Println(final)
    }
    

    您现在应该可以在final 上使用encoding/json 库了。

    【讨论】:

      【解决方案3】:

      另一种选择是逐行解析每一行,然后将每一行添加到代码中的集合(即切片)中,Go为此提供了一行scanner

      yourCollection := []yourObject{}
      scanner := bufio.NewScanner(YOUR_SOURCE)
      for scanner.Scan() {
          obj, err := PARSE_JSON_INTO_yourObject(scanner.Text())
          if err != nil {
             // something
          }
          yourCollection = append(yourCollection, obj)
      }
      if err := scanner.Err(); err != nil {
          fmt.Fprintln(os.Stderr, "reading standard input:", err)
      }
      

      【讨论】:

        【解决方案4】:

        您可以逐行从文件中读取 ndjson 并对其进行解析,然后对其应用逻辑操作。在下面的示例中,我没有从文件中读取,而是使用了 JSON 字符串数组。

        import (
            "encoding/json"
            "fmt"
        )
        
        type NestedObject struct {
            D string
            E string
        }
        
        type OuterObject struct {
            A string
            B string
            C []NestedObject
        }
        
        func main() {
        
            myJsonString := []string{`{"A":"1","B":"2","C":[{"D":"100","E":"10"}]}`, `{"A":"11","B":"21","C":[{"D":"1001","E":"101"}]}`}
            for index, each := range myJsonString {
                fmt.Printf("Index value [%d] is [%v]\n", index, each)
                var obj OuterObject
                json.Unmarshal([]byte(each), &obj)
                fmt.Printf("a: %v, b: %v, c: %v", obj.A, obj.B, obj.C)
                fmt.Println()
            }
        }
        

        输出:

        Index value [0] is [{"A":"1","B":"2","C":[{"D":"100","E":"10"}]}]
        a: 1, b: 2, c: [{100 10}]
        Index value [1] is [{"A":"11","B":"21","C":[{"D":"1001","E":"101"}]}]
        a: 11, b: 21, c: [{1001 101}]
        

        Try it on golang play

        【讨论】:

          猜你喜欢
          • 2020-10-07
          • 1970-01-01
          • 1970-01-01
          • 2011-05-11
          • 1970-01-01
          • 2021-03-19
          • 1970-01-01
          • 1970-01-01
          • 2017-09-13
          相关资源
          最近更新 更多