Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NullableRelationship support #23

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

joekarl
Copy link

@joekarl joekarl commented Jul 5, 2024

http://jsonapi.org/format/#document-resource-object-relationships
http://jsonapi.org/format/#document-resource-object-linkage
Relationships can have a data node set to null (e.g. to disassociate the relationship)

The NullableRelationship type allows this data to be serialized/de-serialized. When serialized, a NullableRelationship with an explicit null will serialize to the appropriate "null" type. Either '"data": null' or '[]'.

Supports slice and regular reference types for serialization, and regular reference types for de-serialization.
The reason to not support slices for de-serialization is we need to decide how to handle the zero type for a NullableRelationship[[]*...] slice. Since we aren't using this and can emulate the nulling behavior by omitting omit-empty we decided to ignore this case for now.

RFC3339Time NullableAttr[time.Time] `jsonapi:"attr,rfc3339_time,rfc3339,omitempty"`
ISO8601Time NullableAttr[time.Time] `jsonapi:"attr,iso8601_time,iso8601,omitempty"`
Bool NullableAttr[bool] `jsonapi:"attr,bool,omitempty"`
NullableComment NullableRelationship[*Comment] `jsonapi:"relation,nullable_comment,omitempty"`
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the intended usage.
By setting the NullableRelationship to an explicit value it will serialize that value, by setting the NullableRelationship to an explicit null will serialize a null value which is intended to clear the relationship.

// unwind that here
if strings.HasPrefix(fieldType.Type.Name(), "NullableRelationship[") {
if m.Kind() == reflect.Ptr {
m = reflect.New(fieldValue.Type().Elem().Elem())
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the grossest part of the code. It feels wrong to "just unwrap one more pointer" but it does work as expected.

},
},
{
desc: "nullable_comment_not_null",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we were to want to support de-serializing slice types we would implement tests for that here.
As it's not included in the PR those sorts of tests are omitted here.

Copy link

@ctrombley ctrombley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this took a while for me to get to @joekarl. I left some comments for review.

nullable.go Outdated Show resolved Hide resolved
request.go Outdated Show resolved Hide resolved
request.go Outdated
// this indicates disassociating the relationship
isExplicitNull = true
} else if relationshipDecodeErr != nil {
fmt.Printf("decode err %v\n", relationshipDecodeErr)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to swallow this error?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about er = fmt.Errorf("decode err %v\n", relationshipDecodeErr)

request.go Show resolved Hide resolved
request.go Outdated

// Explicit null supplied for the field value
// If a nullable relationship we set the
if isExplicitNull && strings.HasPrefix(fieldType.Type.Name(), "NullableRelationship[") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be enough to simply check isExplicitNull? It looks like the only way it can be true here is if we have a NullableRelationship.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think something like this should be ok:
if isExplicitNull {
fieldValue.Set(reflect.MakeMapWithSize(fieldValue.Type(), 1))
fieldValue.SetMapIndex(reflect.ValueOf(false), m)
} I can run the tests to ensure they still pass

response.go Outdated Show resolved Hide resolved
@netramali netramali requested a review from a team as a code owner January 24, 2025 17:31
Copy link

hashicorp-cla-app bot commented Jan 24, 2025

CLA assistant check
All committers have signed the CLA.

@netramali netramali force-pushed the feat/nullable_relationship branch from 769caae to f63a032 Compare January 24, 2025 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants