英文:
Parsing explicit arrays
问题
我正在尝试解析来自服务器的这种类型的响应:
[[1,"a","b",2,"000000",[[1,2,3],[1,2,3]],"x","y","z",[[1,2,3],[1,2,3]]]]
除了编写自己的解析器来处理这种类型的消息之外,是否有一种标准的方法来解释这个问题,我不知道吗?
英文:
I'm trying to parse this type of response from a server:
[[1,"a","b",2,"000000",[[1,2,3],[1,2,3]],"x","y","z",[[1,2,3],[1,2,3]]]]
Besides writing my own hack'ish parser for this type of messages is there a standard way to interpret this that I'm not aware of?
答案1
得分: 7
你的输入是一个JSON字符串。在Go语言中,你可以使用encoding/json
包来解码它。
通常情况下,当已知JSON字符串的结构时,可以构建一个对应该结构的Go struct
类型,并将其解组为该struct
类型的值。
如果结构未知或者可变,可以解组为interface{}
类型的值,该类型可以是任何JSON数据的目标:
s := `[[1,"a","b",2,"000000",[[1,2,3],[1,2,3]],"x","y","z",[[1,2,3],[1,2,3]]]]`
var v interface{}
if err := json.Unmarshal([]byte(s), &v); err != nil {
fmt.Println(err)
return
}
fmt.Println(v)
fmt.Printf("%#v\n", v)
输出结果(在Go Playground上尝试):
[[1 a b 2 000000 [[1 2 3] [1 2 3]] x y z [[1 2 3] [1 2 3]]]]
[]interface {}{[]interface {}{1, "a", "b", 2, "000000", []interface {}{[]interface {}{1, 2, 3}, []interface {}{1, 2, 3}}, "x", "y", "z", []interface {}{[]interface {}{1, 2, 3}, []interface {}{1, 2, 3}}}}
如你所见,结果是一个包含不同类型元素(JSON数字、字符串甚至更多切片)的切片的切片。
下面是添加缩进以更好地了解它的输出结果(使用Go的[复合字面量][4]语法):
```go
[]interface{}{
[]interface{}{
1, "a", "b", 2, "000000",
[]interface{}{
[]interface{}{1, 2, 3},
[]interface{}{1, 2, 3}},
"x", "y", "z",
[]interface{}{
[]interface{}{1, 2, 3},
[]interface{}{1, 2, 3},
},
},
}
当然,这并不是很方便,因为你必须使用类型断言来从类型为interface{}
的“通用”值中“提取”值,例如提取前两个非数组值(还打印它们的类型以进行验证):
fmt.Printf("%T %[1]v\n", v.([]interface{})[0].([]interface{})[0])
fmt.Printf("%T %[1]v\n", v.([]interface{})[0].([]interface{})[1])
输出结果:
float64 1
string a
值得注意的是,尽管JSON中的数字可以是整数(除非另外指定了其他类型),但在Go中,它们被解组为float64
类型的值。
英文:
Your input is a JSON string. In Go, you can use the encoding/json
package to decode it.
Usually, when the structure of the JSON string is known prior, a Go struct
type can be constructed which models it, and then you can unmarshal into a value of that struct
type.
If the structure is unknown or is varying, you may unmarshal into a value of type interface{}
which can be the target of any JSON data:
s := `[[1,"a","b",2,"000000",[[1,2,3],[1,2,3]],"x","y","z",[[1,2,3],[1,2,3]]]]`
var v interface{}
if err := json.Unmarshal([]byte(s), &v); err != nil {
fmt.Println(err)
return
}
fmt.Println(v)
fmt.Printf("%#v\n", v)
Output (try it on the Go Playground):
[[1 a b 2 000000 [[1 2 3] [1 2 3]] x y z [[1 2 3] [1 2 3]]]]
[]interface {}{[]interface {}{1, "a", "b", 2, "000000", []interface {}{[]interface {}{1, 2, 3}, []interface {}{1, 2, 3}}, "x", "y", "z", []interface {}{[]interface {}{1, 2, 3}, []interface {}{1, 2, 3}}}}
As you can see, the result is a slice of slices, with elements of varying types (JSON numbers, strings and even more slices).
Here's the same output adding indentation to get a better feeling of it (using Go's composite literal syntax):
[]interface{}{
[]interface{}{
1, "a", "b", 2, "000000",
[]interface{}{
[]interface{}{1, 2, 3},
[]interface{}{1, 2, 3}},
"x", "y", "z",
[]interface{}{
[]interface{}{1, 2, 3},
[]interface{}{1, 2, 3},
},
},
}
Of course this is not very convenient, as you have to use type assertion to "extract" values from this "generic" value of type interface{}
, for example to extract the first 2 non-arrays values (also printing their types for verification):
fmt.Printf("%T %[1]v\n", v.([]interface{})[0].([]interface{})[0])
fmt.Printf("%T %[1]v\n", v.([]interface{})[0].([]interface{})[1])
Output:
float64 1
string a
Worth noting that JSON numbers in Go are unmarshaled to a value of type float64
even though they could be integers (unless another type is explicitly specified).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论