forked from Mirrors/jsonapi
Feature/omitempty (#35)
* Implemented a failing test demonstrating the intended behaviour of the omitempty annotation. * Updated the failing test to ensure that unset field without the "omitempty" annotation are not inadvertently omitted. * Working implementation of the "omitempty" annotation for fields that are of any type. * Update the readme to include a brief description of how to use the `omitempty` in a attr field. * Update the json example also using a uint for type variety.
This commit is contained in:
parent
3b09fe9cb9
commit
de4994e265
13
README.md
13
README.md
|
@ -63,6 +63,7 @@ type Comment struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
PostId int `json:"post_id"`
|
PostId int `json:"post_id"`
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
|
Likes uint `json:"likes_count,omitempty"`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -127,6 +128,7 @@ type Comment struct {
|
||||||
Id int `jsonapi:"primary,comments"`
|
Id int `jsonapi:"primary,comments"`
|
||||||
PostId int `jsonapi:"attr,post_id"`
|
PostId int `jsonapi:"attr,post_id"`
|
||||||
Body string `jsonapi:"attr,body"`
|
Body string `jsonapi:"attr,body"`
|
||||||
|
Likes uint `jsonapi:"attr,likes-count,omitempty"`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -149,14 +151,17 @@ types are shown in the examples, but not required.
|
||||||
#### `attr`
|
#### `attr`
|
||||||
|
|
||||||
```
|
```
|
||||||
`jsonapi:"attr,<key name in attributes hash>"`
|
`jsonapi:"attr,<key name in attributes hash>,<optional: omitempty>"`
|
||||||
```
|
```
|
||||||
|
|
||||||
These fields' values will end up in the `attributes`hash for a record.
|
These fields' values will end up in the `attributes`hash for a record.
|
||||||
The first argument must be, `attr`, and the second should be the name
|
The first argument must be, `attr`, and the second should be the name
|
||||||
for the key to display in the `attributes` hash for that record. The
|
for the key to display in the `attributes` hash for that record. The optional
|
||||||
spec indicates that `attributes` key names should be dasherized for
|
third argument is `omitempty` - if it is present the field will not be present
|
||||||
multiple word field names.
|
in the `"attributes"` if the field's value is equivalent to the field types
|
||||||
|
empty value (ie if the `count` field is of type `int`, `omitempty` will omit the
|
||||||
|
field when `count` has a value of `0`). Lastly, the spec indicates that
|
||||||
|
`attributes` key names should be dasherized for multiple word field names.
|
||||||
|
|
||||||
#### `relation`
|
#### `relation`
|
||||||
|
|
||||||
|
|
11
response.go
11
response.go
|
@ -255,11 +255,16 @@ func visitModelNode(model interface{}, included *map[string]*Node, sideload bool
|
||||||
node.Attributes[args[1]] = tm.Unix()
|
node.Attributes[args[1]] = tm.Unix()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strAttr, ok := fieldValue.Interface().(string)
|
// Dealing with a fieldValue that is not a time
|
||||||
|
emptyValue := reflect.Zero(fieldValue.Type())
|
||||||
|
|
||||||
if ok && strAttr == "" && omitEmpty {
|
// See if we need to omit this field
|
||||||
|
if omitEmpty && fieldValue.Interface() == emptyValue.Interface() {
|
||||||
continue
|
continue
|
||||||
} else if ok {
|
}
|
||||||
|
|
||||||
|
strAttr, ok := fieldValue.Interface().(string)
|
||||||
|
if ok {
|
||||||
node.Attributes[args[1]] = strAttr
|
node.Attributes[args[1]] = strAttr
|
||||||
} else {
|
} else {
|
||||||
node.Attributes[args[1]] = fieldValue.Interface()
|
node.Attributes[args[1]] = fieldValue.Interface()
|
||||||
|
|
|
@ -36,6 +36,51 @@ type Comment struct {
|
||||||
Body string `jsonapi:"attr,body"`
|
Body string `jsonapi:"attr,body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Book struct {
|
||||||
|
ID int `jsonapi:"primary,books"`
|
||||||
|
Author string `jsonapi:"attr,author"`
|
||||||
|
ISBN string `jsonapi:"attr,isbn"`
|
||||||
|
Title string `jsonapi:"attr,title,omitempty"`
|
||||||
|
Pages *uint `jsonapi:"attr,pages,omitempty"`
|
||||||
|
PublishedAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitsEmptyAnnotation(t *testing.T) {
|
||||||
|
book := &Book{
|
||||||
|
Author: "aren55555",
|
||||||
|
PublishedAt: time.Now().AddDate(0, -1, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
out := bytes.NewBuffer(nil)
|
||||||
|
if err := MarshalOnePayload(out, book); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonData map[string]interface{}
|
||||||
|
if err := json.Unmarshal(out.Bytes(), &jsonData); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
attributes := jsonData["data"].(map[string]interface{})["attributes"].(map[string]interface{})
|
||||||
|
|
||||||
|
// Verify that the specifically omitted field were omitted
|
||||||
|
if val, exists := attributes["title"]; exists {
|
||||||
|
t.Fatalf("Was expecting the data.attributes.title key/value to have been omitted - it was not and had a value of %v", val)
|
||||||
|
}
|
||||||
|
if val, exists := attributes["pages"]; exists {
|
||||||
|
t.Fatalf("Was expecting the data.attributes.pages key/value to have been omitted - it was not and had a value of %v", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the implicity omitted fields were omitted
|
||||||
|
if val, exists := attributes["PublishedAt"]; exists {
|
||||||
|
t.Fatalf("Was expecting the data.attributes.PublishedAt key/value to have been implicity omitted - it was not and had a value of %v", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the unset fields were not omitted
|
||||||
|
if _, exists := attributes["isbn"]; !exists {
|
||||||
|
t.Fatal("Was expecting the data.attributes.isbn key/value to have NOT been omitted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHasPrimaryAnnotation(t *testing.T) {
|
func TestHasPrimaryAnnotation(t *testing.T) {
|
||||||
testModel := &Blog{
|
testModel := &Blog{
|
||||||
ID: 5,
|
ID: 5,
|
||||||
|
|
Loading…
Reference in New Issue