@@ -409,6 +409,72 @@ func (post Post) JSONAPIRelationshipMeta(relation string) *Meta {
409409}
410410```
411411
412+ ### Nullable attributes
413+
414+ Certain APIs may interpret the meaning of ` null ` attribute values as significantly
415+ different from unspecified values (those that do not show up in the request).
416+ The default use of the ` omitempty ` struct tag does not allow for sending
417+ significant ` null ` s.
418+
419+ A type is provided for this purpose if needed: ` NullableAttr[T] ` . This type
420+ provides an API for sending and receiving significant ` null ` values for
421+ attribute values of any type.
422+
423+ In the example below, a payload is presented for a fictitious API that makes use
424+ of significant ` null ` values. Once enabled, the ` UnsettableTime ` setting can
425+ only be disabled by updating it to a ` null ` value.
426+
427+ The payload struct below makes use of a ` NullableAttr ` with an inner ` time.Time `
428+ to allow this behavior:
429+
430+ ``` go
431+ type Settings struct {
432+ ID int ` jsonapi:"primary,videos"`
433+ UnsettableTime jsonapi.NullableAttr [time.Time ] ` jsonapi:"attr,unsettable_time,rfc3339,omitempty"`
434+ }
435+ ```
436+
437+ To enable the setting as described above, an non-null ` time.Time ` value is
438+ sent to the API. This is done by using the exported
439+ ` NewNullableAttrWithValue[T]() ` method:
440+
441+ ``` go
442+ s := Settings {
443+ ID : 1 ,
444+ UnsettableTime : jsonapi.NewNullableAttrWithValue [time.Time ](time.Now ()),
445+ }
446+ ```
447+
448+ To disable the setting, a ` null ` value needs to be sent to the API. This is done
449+ by using the exported ` NewNullNullableAttr[T]() ` method:
450+
451+ ``` go
452+ s := Settings {
453+ ID : 1 ,
454+ UnsettableTime : jsonapi.NewNullNullableAttr [time.Time ](),
455+ }
456+ ```
457+
458+ Once a payload has been marshaled, the attribute value is flattened to a
459+ primitive value:
460+ ```
461+ "unsettable_time": "2021-01-01T02:07:14Z",
462+ ```
463+
464+ Significant nulls are also included and flattened, even when specifying ` omitempty ` :
465+ ```
466+ "unsettable_time": null,
467+ ```
468+
469+ Once a payload is unmarshaled, the target attribute field is hydrated with
470+ the value in the payload and can be retrieved with the ` Get() ` method:
471+ ``` go
472+ t , err := s.UnsettableTime .Get ()
473+ ```
474+
475+ All other struct tags used in the attribute definition will be honored when
476+ marshaling and unmarshaling non-null values for the inner type.
477+
412478### Custom types
413479
414480Custom types are supported for primitive types, only, as attributes. Examples,
0 commit comments