dtd14883 2019-08-01 18:28
浏览 193
已采纳

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

I realize there are a lot of similar questions but I am still not able to find the answer for my problem.

Here is how relevant part of my JSON file looks like:

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

Here is how I defined my struct:

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

I assume that I will always get 1 element in the "roi" array. Please note that I need to keep this structure for many different purposes.

I want to parse that 1 element inside roi array into RoI struct. Here is what I have tried so far:

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
}

When I print out detectionResMap["roi"] using:

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

I get the following output:

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

But, once I try to Unmarshal detectionResMap["roi"] into RoI using:

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
}

I get the following: { 0 0 0 0}

If I try to change it to []RoI I get:

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

Any help will be appreciated

  • 写回答

1条回答 默认 最新

  • doucong6884 2019-08-01 18:59
    关注

    Your attempt doesn't work because roiByteArr is {"roi": [{ ... }]}, this doesn't match config.RoI nor []config.RoI.


    You can either declare a type that matches the 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

    Or properly retrieve the object that matches your stuct:

    // 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

    Or implement a custom unmarshaler:

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条