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

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

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?