json - 如何将包含数组的 JSON 对象转换为单个 Struct 实例

标签 json go unmarshalling

我意识到有很多类似的问题,但我仍然无法找到问题的答案。

这是我的 JSON 文件的相关部分的样子:

{ 
    ...,
    "roi": {
        "roi": [
            {
                "id": "original",
                "x": 600,
                "y": 410,
                "width": 540.0,
                "height": 240.0
            }
        ]
    },
    ...
}

这是我定义结构的方式:

type RoI struct {
    Id     string  `json:"string"`                            // Default Value: "original"
    Width  float64 `json:"width" validate:"gte=0,lte=10000"`  // RoI width (from 0 - 10000) - how much we move to the right from (X,Y) point
    Height float64 `json:"height" validate:"gte=0,lte=10000"` // RoI height (from 0 - 10000) - how much we move down from the (X,Y) point
    X      float64 `json:"x" validate:"gte=0,lte=10000"`      // X coordinate which together with Y coordinate forms a top left corner of the RoI (from 0 - 10000)
    Y      float64 `json:"y" validate:"gte=0,lte=10000"`      // Y coordinate which together with X coordinate forms a top left corner of the RoI (from 0 - 10000)
}

我假设我总是会在 "roi" 数组中得到 1 个元素。请注意,出于许多不同的目的,我需要保留此结构。

我想将 roi 数组中的 1 个元素解析为 RoI 结构。到目前为止,这是我尝试过的:

var detectionResMap = make(map[string]interface{})
err = json.Unmarshal(fileByteArr, &detectionResMap)
if err != nil {
    glog.Errorf("Error occurred while trying to Unmarshal JSON data into detectionResMap. Error message - %v", err)
    return err
}

当我打印出 detectionResMap["roi"] 时使用:

glog.Infof("[INFO]: %v", reflect.TypeOf(detectionResMap["roi"]))
glog.Infof("[INFO]: %v", detectionResMap["roi"])

我得到以下输出:

I0801 19:56:45.392362  125787 v2.go:87] [INFO]: map[string]interface {}
I0801 19:56:45.392484  125787 v2.go:88] [INFO]: map[roi:[map[height:240 id:original width:540 x:600 y:410]]]

但是,一旦我尝试使用以下方法将 detectionResMap["roi"] 解码为 RoI:

roiByteArr, err := json.Marshal(detectionResMap["roi"])
if err != nil {
    glog.Errorf("Error occurred while trying to Marshal detectionResMap[\"roi\"] into byte array. Error message - %v", err)
    return err
}

roi := config.RoI{}
if err := json.Unmarshal(roiByteArr, &roi); err != nil {
    glog.Errorf("Error occurred while trying to unmarshal roi data. Error message - %v", err)
    return err
}

我得到以下信息: { 0 0 0 0}

如果我尝试将其更改为 []RoI,我会得到:

json: cannot unmarshal object into Go value of type []config.RoI

任何帮助将不胜感激

最佳答案

您的尝试无效,因为 roiByteArr{"roi": [{ ... }]},这与 config 不匹配。 RoI[]config.RoI


您可以声明一个与 json 匹配的类型:

type roiobj struct {
    RoI struct {
        RoI []RoI `json:"roi"`
    } `json:"roi"`
}

var obj roiobj
if err := json.Unmarshal(fileByteArr, &obj); err != nil {
    panic(err)
}
roi := obj.RoI.RoI[0]

playground

或正确检索与您的结构匹配的对象:

// in your real code do not omit safe type assertion like i'm doing here.
obj := detectionResMap["roi"].(map[string]interface{})["roi"].([]interface{})[0]
roiByteArr, err := json.Marshal(obj)
if err != nil {
    return err
}

roi := config.RoI{}
if err := json.Unmarshal(roiByteArr, &roi); err != nil {
    return err
}

playground

或者实现自定义解码器:

func (r *RoI) UnmarshalJSON(b []byte) error {
    type roi RoI
    var obj struct {
        RoI []roi
    }
    if err := json.Unmarshal(b, &obj); err != nil {
        return err
    }
    *r = RoI(obj.RoI[0])
    return nil
}

var fileobj struct {
    // ...
    RoI RoI `json:"roi"`
    // ...
}
if err := json.Unmarshal(fileByteArr, &fileobj); err != nil {
    panic(err)
}
roi := fileobj.RoI

playground

关于json - 如何将包含数组的 JSON 对象转换为单个 Struct 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57315029/

相关文章:

javascript - JSON类数组对象,添加项目

go - sendgrid go send get 错误意外的 EOF

go - 检查纬度/经度点是否在区域内

java - 无法使用 JAXB 正确解码包含选项卡的 XML 文件?

java - JAXB - 编码/解码问题

json - 如果对象返回为空字符串而不是空结构,如何解码 json 对象

json - 在 Go 中编码 []interface{}

javascript - 如何将此 JSON 保存到 MongoDB Compass 提供服务的 mongoDB 数据库?

json - Docker-如何检查容器的卷路径?

json - 获取一个 JSON 字符串,将其解码为 map[string]interface{},编辑并将其编码为 []byte 似乎比应该的更复杂