I'm trying to customize the output of MarshalJSON
, using the interface:
func (m *RawMessage) MarshalJSON() ([]byte, error)
I followed that tutorial: http://choly.ca/post/go-json-marshalling/
My purpose is removing replace one of the fields with true/false (if set or not), so I ended up writing that function:
func (u *Edition) MarshalJSON() ([]byte, error) {
var vaultValue bool
vaultValue = true
var onlineValue bool
vaultValue = false
fmt.Println("here")
if u.Vault == nil {
vaultValue = false
}
if u.Online == nil {
onlineValue = false
}
type AliasEdition Edition
return json.Marshal(&struct {
Vault bool `json:"vault,omitempty"`
Online bool `json:"online,omitempty"`
*AliasEdition
}{
Vault: vaultValue,
Online: onlineValue,
AliasEdition: (*Alias)(u),
})
}
The JSON is created from a map with the following instruction:
json.NewEncoder(w).Encode(EditionsMap)
Obviously EditionsMap
is a Map of Edition
s structures:
var EditionsMap map[string]datamodel.Edition
The problem is that the MarshalJSON
function apparently is never called.
Probably I'm doing something wrong, but I cannot understand what is the problem, my understanding is that I just need to implement that function in order to get it called.
This is because you declared the Edition.MarshalJSON()
method with pointer receiver:
func (u *Edition) MarshalJSON() ([]byte, error)
And you try to marshal non-pointer values (your map contains datamodel.Edition
values):
var EditionsMap map[string]datamodel.Edition
// ...
json.NewEncoder(w).Encode(EditionsMap)
Methods with pointer receiver are not part of the method set of the corresponding non-pointer type. The method set of type datamodel.Edition
does not contain the method MarshalJSON()
.
Spec: Method sets:
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type
T
consists of all methods declared with receiver typeT
. The method set of the corresponding pointer type*T
is the set of all methods declared with receiver*T
orT
(that is, it also contains the method set ofT
).
Try to marshal pointer values, define your map to contain pointers:
var EditionsMap map[string]*datamodel.Edition
// ...
if err := json.NewEncoder(w).Encode(EditionsMap); err != nil {
panic(err) // HANDLE error somehow, do not omit it like in your example!
}
Values of the pointer type *Edition
does have a method MarshalJSON()
which will be called properly by the json
package. Try a working example of this on the Go Playground.
Another option would be to define the Edition.MarshalJSON()
method with value receiver:
func (u Edition) MarshalJSON() ([]byte, error)
And this way it would work no matter if you marshal pointer or non-pointer values, as the methods with value receiver are part of the method set of both the Edition
type and the corresponding *Edition
pointer type. Try a working example of this variant on the Go Playground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With