英文:
How to parse JSON when array dimension depends on some other field of the same JSON in Go?
问题
任务是将GeoJSON存储到Go数据结构中。我面临的问题是JSON中有一个名为coordinates
的数组,其维度随同一JSON中的另一个字段type
而变化。
例如:
{
"type": "Point",
"coordinates": [100.0, 0.0]
}
{
"type": "LineString",
"coordinates": [
[100.0, 0.0],
[101.0, 1.0]
]
}
{
"type": "MultiPolygon",
"coordinates": [
[
[
[102.0, 2.0],
[103.0, 2.0],
[103.0, 3.0],
[102.0, 3.0],
[102.0, 2.0]
]
],
[
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
],
[
[100.2, 0.2],
[100.2, 0.8],
[100.8, 0.8],
[100.8, 0.2],
[100.2, 0.2]
]
]
]
}
现在,如果我创建一个2D、1D、3D和4D的数组,那么会缺少相应的情况。
我的数据结构如下:
type Geometry struct {
Type string `json:"type"`
Coordinates[][][][] float64 `json:"coordinates"`
}
...
var data Geometry
json.Unmarshal([]byte(geoJsonString), &data)
我对Go语言和JSON都不太熟悉。请帮帮我。
英文:
The task is to store GeoJSON into Go data structure. Problem I am facing that there is an array named coordinate
in the JSON whose dimension changes with an other field in the same JSON named type
.
For example:
{
"type": "Point",
"coordinates": [100.0, 0.0]
}
{
"type": "LineString",
"coordinates": [
[100.0, 0.0],
[101.0, 1.0]
]
}
{
"type": "MultiPolygon",
"coordinates": [
[
[
[102.0, 2.0],
[103.0, 2.0],
[103.0, 3.0],
[102.0, 3.0],
[102.0, 2.0]
]
],
[
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
],
[
[100.2, 0.2],
[100.2, 0.8],
[100.8, 0.8],
[100.8, 0.2],
[100.2, 0.2]
]
]
]
}
Now if I am making an array of 2D then 1D, 3D and 4D cases are missing.
My data structure is something like this:
type Geometry struct {
Type string `json:"type"`
Coordinates[][][][] float64 `json:"coordinates"`
}
...
var data Geometry
json.Unmarshal([] byte(geoJsonString), &data)
I am new to language Go and JSON. Please help me out.
答案1
得分: 1
最好使用现有的包来处理。例如:https://pkg.go.dev/github.com/paulmach/go.geojson#UnmarshalGeometry
如果你想要手动处理具有不同JSON结构的数据,可以使用encoding/json
中的两种主要方法:
- 将可变类型字段解码为
json.RawMessage
,然后继续解码为所需的具体类型。
type geometry struct {
Type string `json:"type"`
Coords json.RawMessage `json:"coordinates"`
}
type lineStringCoords [][]float64
var data geometry
if err := json.Unmarshal(input, &data); err != nil {
return err
}
switch data.Type {
case "LineString":
var lineString lineStringCoords
if err := json.Unmarshal(data.Coords, &lineString); err != nil {
...
}
...
}
- 将可变类型字段解码为
interface{}
,然后使用类型断言提取数据。这或多或少是github.com/paulmac/go.geojson
使用的方法。这允许你解码/探索任意的JSON,但实现起来更加复杂。
type geometry struct {
Type string `json:"type"`
Coords interface{} `json:"coordinates"`
}
var data geometry
if err := json.Unmarshal(input, &data); err != nil {
return err
}
switch data.Type {
case "LineString":
slice, ok := data.Coords.([]interface{})
// 继续手动提取切片并复制到适当的输出结构中。
...
}
英文:
It's probably best to use a pre-existing package. Eg: https://pkg.go.dev/github.com/paulmach/go.geojson#UnmarshalGeometry
There are 2 main approaches if you would like to handle varied JSON structures manually with encoding/json
:
- Decode the variable type field into a
json.RawMessage
and continue decoding into the specific type you need.
type geometry struct {
Type string `json:"type"`
Coords json.RawMessage `json:"coordinates"`
}
type lineStringCoords [][]float64
var data geometry
if err := json.Unmarshal(input, &data); err != nil {
return err
}
switch data.Type {
case "LineString":
var lineString lineStringCoords
if err := json.Unmarshal(data.Coords, &lineString); err != nil {
...
}
...
}
- Decode the variable type field into an
interface{}
and use type assertions to extract the data. This is more or less the approach used bygithub.com/paulmac/go.geojson
. This allows you to decode/explore arbitrary JSON but is more complicated to implement.
type geometry struct {
Type string `json:"type"`
Coords interface{} `json:"coordinates"`
}
var data geometry
if err := json.Unmarshal(input, &data); err != nil {
return err
}
switch data.Type {
case "LineString":
slice, ok := data.Coords.([]interface{})
// Continue manually extracting the slices and copy into the appropriate output struct.
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论