Skip to content

Commit

Permalink
Treat pointers to nil slices as empty for Patient updates (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
gffking authored Feb 3, 2025
1 parent bc25044 commit 5497b5a
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 27 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (

require (
cloud.google.com/go v0.118.0
github.com/google/go-cmp v0.6.0
github.com/google/go-querystring v1.1.0
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0
Expand Down
33 changes: 33 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package elation

import "encoding/json"

// NonNullJSONArray ensures that nil slices are marshalled to "[]" instead of "null". It also ensures that empty JSON arrays
// are marshalled to nil slices.
type NonNullJSONArray[T any] []T

func (nnja NonNullJSONArray[T]) MarshalJSON() ([]byte, error) {
if nnja == nil {
nnja = make([]T, 0)
}

return json.Marshal([]T(nnja))
}

func (nnja *NonNullJSONArray[T]) UnmarshalJSON(data []byte) error {
type alias NonNullJSONArray[T]
var a alias

err := json.Unmarshal(data, &a)
if err != nil {
return err
}

if len(a) == 0 {
return nil
}

*nnja = NonNullJSONArray[T](a)

return nil
}
71 changes: 71 additions & 0 deletions json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package elation

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
)

func TestNonNullJSONArray_MarshalJSON(t *testing.T) {
testCases := map[string]struct {
value NonNullJSONArray[string]
expectedBytes []byte
}{
"nil value": {
value: nil,
expectedBytes: []byte("[]"),
},
"empty array": {
value: NonNullJSONArray[string]{},
expectedBytes: []byte("[]"),
},
"non-empty array": {
value: NonNullJSONArray[string]{"alvin", "simon", "theodore"},
expectedBytes: []byte(`["alvin","simon","theodore"]`),
},
}

for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)

bytes, err := testCase.value.MarshalJSON()
assert.NoError(err)

assert.Equal(testCase.expectedBytes, bytes)
})
}
}

func TestNonNullJSONArray_UnmarshalJSON(t *testing.T) {
testCases := map[string]struct {
bytes []byte
expectedValue NonNullJSONArray[string]
}{
"empty array": {
bytes: []byte("[]"),
expectedValue: nil,
},
"null": {
bytes: []byte("null"),
expectedValue: nil,
},
"non-empty array": {
bytes: []byte(`["foo", "bar"]`),
expectedValue: NonNullJSONArray[string]{"foo", "bar"},
},
}

for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)

var val NonNullJSONArray[string]
err := json.Unmarshal(testCase.bytes, &val)
assert.NoError(err)

assert.Equal(testCase.expectedValue, val)
})
}
}
46 changes: 23 additions & 23 deletions patient.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,29 +261,29 @@ func (s *PatientService) Get(ctx context.Context, id int64) (*Patient, *http.Res
}

type PatientUpdate struct {
ActualName *string `json:"actual_name,omitempty"`
Address *PatientAddress `json:"address,omitempty"`
Consents *[]*PatientConsent `json:"consents,omitempty"`
DOB *string `json:"dob,omitempty"`
Emails *[]*PatientEmail `json:"emails,omitempty"`
Ethnicity *string `json:"ethnicity,omitempty"`
FirstName *string `json:"first_name,omitempty"`
GenderIdentity *string `json:"gender_identity,omitempty"`
Insurances *[]*PatientInsuranceUpdate `json:"insurances,omitempty"`
LastName *string `json:"last_name,omitempty"`
LegalGenderMarker *string `json:"legal_gender_marker,omitempty"`
MiddleName *string `json:"middle_name,omitempty"`
Notes *string `json:"notes,omitempty"`
PatientStatus *PatientStatusUpdate `json:"patient_status,omitempty"`
Phones *[]*PatientPhone `json:"phones,omitempty"`
PreferredLanguage *string `json:"preferred_language,omitempty"`
PrimaryCareProviderNPI *string `json:"primary_care_provider_npi,omitempty"`
PrimaryPhysician *int64 `json:"primary_physician,omitempty"`
Pronouns *string `json:"pronouns,omitempty"`
Race *string `json:"race,omitempty"`
Sex *string `json:"sex,omitempty"`
SexualOrientation *string `json:"sexual_orientation,omitempty"`
SSN *string `json:"ssn,omitempty"`
ActualName *string `json:"actual_name,omitempty"`
Address *PatientAddress `json:"address,omitempty"`
Consents *NonNullJSONArray[*PatientConsent] `json:"consents,omitempty"`
DOB *string `json:"dob,omitempty"`
Emails *NonNullJSONArray[*PatientEmail] `json:"emails,omitempty"`
Ethnicity *string `json:"ethnicity,omitempty"`
FirstName *string `json:"first_name,omitempty"`
GenderIdentity *string `json:"gender_identity,omitempty"`
Insurances *NonNullJSONArray[*PatientInsuranceUpdate] `json:"insurances,omitempty"`
LastName *string `json:"last_name,omitempty"`
LegalGenderMarker *string `json:"legal_gender_marker,omitempty"`
MiddleName *string `json:"middle_name,omitempty"`
Notes *string `json:"notes,omitempty"`
PatientStatus *PatientStatusUpdate `json:"patient_status,omitempty"`
Phones *NonNullJSONArray[*PatientPhone] `json:"phones,omitempty"`
PreferredLanguage *string `json:"preferred_language,omitempty"`
PrimaryCareProviderNPI *string `json:"primary_care_provider_npi,omitempty"`
PrimaryPhysician *int64 `json:"primary_physician,omitempty"`
Pronouns *string `json:"pronouns,omitempty"`
Race *string `json:"race,omitempty"`
Sex *string `json:"sex,omitempty"`
SexualOrientation *string `json:"sexual_orientation,omitempty"`
SSN *string `json:"ssn,omitempty"`
}

type PatientInsuranceUpdate struct {
Expand Down
Loading

0 comments on commit 5497b5a

Please sign in to comment.