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