【问题标题】:Parse (arbitrary) previously know data from JSON using GO使用 GO 解析(任意)先前知道来自 JSON 的数据
【发布时间】:2021-10-02 19:21:31
【问题描述】:

我必须解析一些 JSON 文件。
问题是:某些字段包含的数据类型因某些外部(已获得)信息而异。
我的问题是:如何使用 golang 执行此操作? 我已经为此寻找了几个小时的解决方案并尝试提出一个解决方案,但我不断收到运行时错误。
另外,我认为类型强制/强制转换可以基于 this post 工作。

我是该语言的新手,所以请您不要太苛刻地回答这个问题。

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
    "unsafe"
)

func main() {
    birdJson := `{
            "blah": "bleh",
            "coord" : [[1,2], [3, 4], [22, 5]]
        }
    `
    var result map[string]interface{}
    json.Unmarshal([]byte(birdJson), &result)
    fmt.Println("result:: ", result)

    c := result["coord"]
    
    cv := reflect.ValueOf(c)
    ct := reflect.TypeOf(c)

    fmt.Println("c value:", cv)
    fmt.Println("c type: ", ct)
    fmt.Println(cv.Interface().([][]int))
}

输出:

result::  map[blah:bleh coord:[[1 2] [3 4] [22 5]]]
c value: [[1 2] [3 4] [22 5]]
c type:  []interface {}
panic: interface conversion: interface {} is []interface {}, not [][]int

goroutine 1 [running]:
main.main()
    /Users/maffei/golab/t.go:27 +0x497
exit status 2

【问题讨论】:

  • 您并没有真正披露 json 的可变性,但为了进行嵌套类型断言,您可以使用如下库:github.com/Jeffail/gabs

标签: json go parsing


【解决方案1】:

目前还不清楚你要做什么,但你可以像这样 Unmarshal:

package main

import (
   "encoding/json"
   "fmt"
)

var birdJson = []byte(`
{
   "blah": "bleh", "coord" : [
      [1,2], [3, 4], [22, 5]
   ]
}
`)

func main() {
   var result struct {
      Blah string
      Coord [][]int
   }
   json.Unmarshal(birdJson, &result)
   fmt.Printf("%+v\n", result) // {Blah:bleh Coord:[[1 2] [3 4] [22 5]]}
}

【讨论】:

  • 这里是imo的首选答案。在解组 JSON 时,如果可能,使用结构体将优于 map[string]interface{} 并直接在代码中键入断言,以提高可读性/维护性。
【解决方案2】:

您不能 type assert 使用单个表达式的嵌套接口。

如果c的动态类型是[][]int,那么可以c.([][]int)

var c interface{} = [][]int{{1,2}, {3,4}}
_, ok := c.([][]int) // ok == true

但是,如果c 的动态类型是[]interface{},那么你必须做c.([]interface{}),然后你必须循环[]interface{} 切片并单独断言每个元素,在您的情况下,它是另一个 []interface{},因此您还需要遍历它,然后键入断言嵌套切片的各个元素。

另请注意,由于 JSON 数字在目标类型为 interface{} 时默认解组为 float64,因此您需要将 conversion 转换为 int 以获得所需的结果

s1 := c.([]interface{})
out := make([][]int, len(s1))
for i := range s1 {
    if s2, ok := s1[i].([]interface{}); ok {
        s3 := make([]int, len(s2))
        for i := range s2 {
            if f64, ok := s2[i].(float64); ok {
                s3[i] = int(f64) // convert float64 to int
            }
        }
        out[i] = s3
    }
}

https://play.golang.org/p/UEdf2VSPg16

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2018-04-20
    相关资源
    最近更新 更多