Reputation: 1015
I have a JSON which contain some static and dynamic data. Below is a sample of JSON
{
"request": { /*Static data start */
"data": {
"object": { /*Static data ends here*/
"user": { /*Dynamic data start here */
"userid": "andmmdn",
"ipaddr": "1.1.1.1",
"noofusers": "100",
"qos": "34",
"id": "kldjflkdfjlkdjfkld",
"domain": "xyz.com" /*Dynamic data ends here */
}
}
}
}
}
Below is the code which can create this JSON
package main
import (
"fmt"
"encoding/json"
)
//ReqJSON struct
type ReqJSON struct {
Request Request `json:"request"`
}
//Request struct
type Request struct {
Data Data `json:"data"`
}
//Data struct
type Data struct {
Object Object `json:"object"`
}
//Object struct
type Object struct {
User User `json:"user"`
}
//User struct
type User struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
func main() {
test := ReqJSON {
Request{
Data: Data{
Object: Object{
User: User{
UserID: "andmmdn",
IPAddr: "1.1.1.1",
Noofusers: "100",
Qos: "34",
ID: "kldjflkdfjlkdjfkld",
Domain: "xyz.com",
},
},
},
},
}
jsonEncode, _ := json.Marshal(test)
jsonIdent, _ := json.MarshalIndent(&test, "", "\t")
fmt.Println(string(jsonEncode))
fmt.Println(string(jsonIdent))
}
As you can see from above it contain struct which doesn't make much sense as they act more like placeholder for nesting the data. So how we make it more optimized. As all the data is being taken care in the last struct. What approach for unmarshaling of the data should be applied as the response will be in same format and want to use the last struct for the same. Any thoughts on the approach. Also how to make a generic struct as I multiple API which uses same struct below is an example
//ReqJSON for populating data
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
Auth Auth `json:"auth"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
//ReqJSON for populating data
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
Error Error `json:"error"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
Upvotes: 2
Views: 309
Reputation: 79774
You can't eliminate the complexity, but you could potentially hide some of it inside of a custom Marshaler:
type Request struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
func (r *Request) MarshalJSON() ([]byte, error) {
type request struct {
Data struct {
Object struct {
User struct {
Request
} `json:"user"`
} `json:"object"`
} `json:"data"`
}
structure := request{Data: data{Object: object{User: user{r}}}}
return json.Marshal(structure)
}
The same approach can be employed in reverse for UnmarshalJSON
, if desired.
Upvotes: 1
Reputation: 31771
If you don't need the wrapping types for anything besides marshaling/unmarshaling, you can define them anonymously:
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
User User `json:"user"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
type User struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
And, borowing from icza's answer, you can add accessor methods to ReqJSON
:
func (j *ReqJSON) User() User { return j.Request.Data.Object.User }
func (j *ReqJSON) SetUser(u User) { j.Request.Data.Object.User = u }
func main() {
var j ReqJSON
j.SetUser(User{
UserID: "_id",
IPAddr: "1.1.1.1",
Noofusers: "100",
Qos: "34",
ID: "kldjflkdfjlkdjfkld",
Domain: "xyz.com",
})
b, err := json.MarshalIndent(j, "", " ")
fmt.Println(err, string(b))
}
Upvotes: 2
Reputation: 418585
That sounds about right. The solution is a little verbose / redundant, but so is the data format you have to deal with.
To work with that easily, you may create helper functions and use them:
func wrap(u User) *ReqJSON {
return &ReqJSON{Request: Request{Data: Data{Object: Object{User: u}}}}
}
func unwrap(r *ReqJSON) User {
return r.Request.Data.Object.User
}
But other than that, you can't really simplify other things.
So marshaling a User
is like:
var u User
data, err := json.Marshal(wrap(u))
Unmarshaling is:
var r *ReqJSON
err := json.Unmarshal(data, &r)
// Check error
u := unwrap(r) // Here we have the user
Upvotes: 1