使用GO解析(任意)先前已知的JSON数据。

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

Parse (arbitrary) previously know data from JSON using GO

问题

我必须解析一些JSON文件。
问题是:某些字段包含的数据类型根据一些外部(已获取的)信息而变化。
我的问题是:如何使用golang来执行此操作?
我已经寻找了几个小时的解决方案,并尝试提出一个解决方案,但我始终遇到运行时错误。
此外,根据这篇帖子,我认为类型强制转换/转换应该可以工作。

对于这门语言,我是一个相当新手,所以请您在回答时不要太苛刻。

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
英文:

I have to parse some JSON files.
The problem is: the type of data some field contains varies according some external (already obtained) information.
My question is: how do I perform this using golang?
I've looked for a solution for this for hours and tried coming up with one, but I keep getting runtime errors.
Also, I thought the type coercion/casting would work based on this post.

I am quite a newbie regarding that language, so I ask you for not being too harsh answering this.

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

The output:

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

答案1

得分: 4

这是一个示例代码,用于解析 JSON 数据。你可以按照以下方式进行解析:

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

这段代码使用了 encoding/json 包中的 Unmarshal 函数来解析 JSON 数据。首先,定义了一个结构体 result,它包含了与 JSON 数据对应的字段。然后,通过调用 json.Unmarshal 函数将 JSON 数据解析到 result 变量中。最后,使用 fmt.Printf 函数打印解析结果。

注意:在实际使用时,你需要根据 JSON 数据的结构定义自己的结构体,并根据需要修改代码。

英文:

It's not really clear what you're trying to do, but you can Unmarshal like this:

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

答案2

得分: 0

你不能使用单个表达式对嵌套接口进行类型断言。

如果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,你需要进行转换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) // 将float64转换为int
			}
		}
		out[i] = s3
	}
}

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

英文:

You cannot type assert nested interfaces with a single expression.

If the dynamic type of c is [][]int, then you can do c.([][]int).

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

However, if the dynamic type of c is []interface{}, then you have to do c.([]interface{}), you then have to loop over the []interface{} slice and type assert each element individually, which, in your case, is another []interface{}, so you'll also need to loop over that and then type assert the individual elements of the nested slice.

Also note that since JSON Numbers are by default unmarshaled as float64 when the target type is interface{}, you'll need to do a conversion to int to get the result you want

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

huangapple
  • 本文由 发表于 2021年7月27日 06:15:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/68536879.html
匿名

发表评论

匿名网友

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

确定