Reputation: 508
Suppose I have an struct like this in go:
type Message struct {
Args []interface{}
Kwargs map[string]interface{}
}
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
How should I marshal message to have a JSON like this?
[[1,2,3,4], {"a": 2, "b":3}]
Upvotes: 1
Views: 800
Reputation: 824
You can add a marshal method to your struct to handle the logic. Something in the lines of
func (m Message) MarshalJSON() ([]byte, error) {
data := make([]interface{}, 0)
data = append(data, m.Args)
data = append(data, m.Kwargs)
return json.Marshal(data)
}
Upvotes: 2
Reputation: 417412
What you want in your output is a JSON array holding the Args
and Kwargs
fields of your message
struct value, so you may get what you want by marshaling the following slice value:
[]interface{}{message.Args, message.Kwargs}
For example:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).
Encode([]interface{}{message.Args, message.Kwargs})
fmt.Println(err)
Output of the above (try it on the Go Playground):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
This works for this specific case. If you want a general solution which marshals fields of a struct value like elements of an array, you may create a helper function that "packs" fields into a slice:
func getFields(i interface{}) (res []interface{}) {
v := reflect.ValueOf(i)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil
}
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if f.CanInterface() {
res = append(res, f.Interface())
}
}
return res
}
The above getFields()
accepts struct values and pointers to structs. Example using it:
message := Message{
[]interface{}{1, 2, 3, 4},
map[string]interface{}{"a": 2, "b": 3},
}
err := json.NewEncoder(os.Stdout).Encode(getFields(message))
fmt.Println(err)
err = json.NewEncoder(os.Stdout).Encode(getFields(&message))
fmt.Println(err)
Output (try it on the Go Playground):
[[1,2,3,4],{"a":2,"b":3}]
<nil>
[[1,2,3,4],{"a":2,"b":3}]
<nil>
Upvotes: 1