I have pulled some data out of a given database - the format however is not correct as per what I want.
Sample struct:
type myStruct struct {
ID int `json:"Id"`
Language string `json:"Language"`
Location string `json:"Location"`
}
Right, I serialize a given map of strings with a custom struct representing the given returned columns:
func transformJSON(extract []map[string]*sql.SqlCell) ([]byte, error) {
return json.MarshalIndent(extract, "", " ")
}
This returns valid JSON, but with the format:
{
{
"id": {
"Value": {
"Long": 12353
}
},
"language": {
"Value": {
"String_": "ja-JP"
}
},
"location": {
"Value": {
"String_": "Osaka"
}
},
Referring to my struct above, I'd like a format as such:
[
{
"Id": 12353,
"Language": "ja-JP",
"Location": "Osaka"
},
// .. other objects
]
Assuming the same input to the func transformJSON
, how would I match the nested keys with the column type values as well?
Should I Marshal
the map first, then transform the data -- or work directly with the []map[string]*sql.SqlCell
data structure before marshal?
In my head, I was thinking along the lines of:
func transformJSON(extract []map[string]*sql.SqlCell) ([]byte, error) {
struct :=[] myStruct{}
// Loop over extract objects, match nested keys, write to struct?
return json.MarshalIndent(struct, "", " ")
}
Create a custom unmarshaler, that unmarshals the entire thing, then converts for you:
type MyStruct struct {
ID int `json:"Id"`
Language string `json:"Language"`
Location string `json:"Location"`
}
type val struct {
Value struct {
String string `json:"String_"`
Long int `json:"Long"`
}
}
func (s *MyStruct) UnmarshalJSON(p []byte) error {
var result struct{
ID val `json:"Id"`
Language val `json:"language"`
Location val `json:"location"`
}
if err := json.Unmarshal(p, &result); err != nil {
return err
}
s.ID = result.ID.Value.Long
s.Language = result.Langauge.Value.String
s.Location= result.Location.Value.String
return nil
}
Note that minimal error checking and data validation is done in this example--I leave that as an exercise for the reader.