Reputation: 875
It looks like jsonapi.Marshal returns an empty json object for a golang struct with a value that is false. I understand that a struct of zero values is considered zero, but as a caller of this API, am I supposed to just know that empty json object means false?
Here is an example. "Active"
is either {"value": true}
or {}
but never {"value": false}
.
package main
import (
"fmt"
"log"
"github.com/DataDog/jsonapi"
"github.com/golang/protobuf/ptypes/wrappers"
)
type MyResource struct {
ID string `jsonapi:"primary,my-resource"`
Active *wrappers.BoolValue `jsonapi:"attribute"`
}
func main() {
// Create an instance of MyResource with Active set to true
resource := &MyResource{
ID: "1",
Active: &wrappers.BoolValue{Value: true},
}
// Marshal the struct into JSON:API format
data, err := jsonapi.Marshal(resource)
if err != nil {
log.Fatalf("Error marshalling resource: %v", err)
}
// Print the JSON result
fmt.Println(string(data))
// Create an instance of MyResource with Active set to false
resource2 := &MyResource{
ID: "1",
Active: &wrappers.BoolValue{Value: false},
}
// Marshal the struct into JSON:API format
data2, err := jsonapi.Marshal(resource2)
if err != nil {
log.Fatalf("Error marshalling resource: %v", err)
}
// Print the JSON result
fmt.Println(string(data2))
}
// prints the following:
// {"data":{"id":"1","type":"my-resource","attributes":{"Active":{"value":true}}}}
// {"data":{"id":"1","type":"my-resource","attributes":{"Active":{}}}}
Thanks!
Upvotes: 0
Views: 56
Reputation: 40296
This is an (increasingly) common pattern and arises because, Golang scalar types don't have a nil
value.
A solution is to create a helper function to convert e.g. bool
to *bool
:
func BoolPtr(b bool) *bool {
return &b
}
And then e.g.:
package main
import (
"testing"
"github.com/DataDog/jsonapi"
)
type MyResource struct {
ID string `jsonapi:"primary,my-resource"`
Active *bool `jsonapi:"attribute"`
}
func BoolPtr(b bool) *bool {
return &b
}
var tests = []struct {
input *MyResource
want string
}{
{
input: &MyResource{
ID: "0",
Active: nil,
},
want: `{"data":{"id":"0","type":"my-resource","attributes":{"Active":null}}}`,
},
{
input: &MyResource{
ID: "1",
Active: BoolPtr(true),
},
want: `{"data":{"id":"1","type":"my-resource","attributes":{"Active":true}}}`,
},
{
input: &MyResource{
ID: "1",
Active: BoolPtr(false),
},
want: `{"data":{"id":"1","type":"my-resource","attributes":{"Active":false}}}`,
},
}
func TestMain(t *testing.T) {
for _, test := range tests {
t.Run(test.input.ID, func(t *testing.T) {
b, err := jsonapi.Marshal(test.input)
if err != nil {
t.Errorf("Error marshalling resource: %v", err)
}
got := string(b)
if got != test.want {
t.Errorf("got: %s\nwant: %s\n", got, test.want)
}
})
}
}
yields:
=== RUN TestMain
=== RUN TestMain/0
=== RUN TestMain/1
=== RUN TestMain/1#01
--- PASS: TestMain (0.00s)
--- PASS: TestMain/0 (0.00s)
--- PASS: TestMain/1 (0.00s)
--- PASS: TestMain/1#01 (0.00s)
PASS
ok .../stackoverflow/79343968 0.002s
Upvotes: 1