@@ -2,15 +2,17 @@ package lduser
22
33import (
44 "encoding/json"
5- "errors "
5+ "reflect "
66
77 "gopkg.in/launchdarkly/go-sdk-common.v2/jsonstream"
88 "gopkg.in/launchdarkly/go-sdk-common.v2/ldvalue"
99)
1010
11- var (
12- errMissingKey = errors .New ("" )
13- )
11+ type missingKeyError struct {}
12+
13+ func (e missingKeyError ) Error () string {
14+ return "User must have a key property"
15+ }
1416
1517// ErrMissingKey returns the standard error value that is used if you try to unmarshal a user from JSON
1618// and the "key" property is either absent or null. This is distinguished from other kinds of unmarshaling
2022// LaunchDarkly does allow a user to have an empty string ("") as a key in some cases, but this is
2123// discouraged since analytics events will not work properly without unique user keys.
2224func ErrMissingKey () error {
23- return errMissingKey
25+ return missingKeyError {}
2426}
2527
2628// This temporary struct allows us to do JSON unmarshalling as efficiently as possible while not requiring
@@ -76,13 +78,23 @@ func (u User) MarshalJSON() ([]byte, error) {
7678// Any property that is either completely omitted or has a null value is ignored and left in an unset
7779// state, except for "key". All users must have a key (even if it is ""), so an omitted or null "key"
7880// property causes the error ErrMissingKey().
81+ //
82+ // Trying to unmarshal any non-struct value, including a JSON null, into a User will return a
83+ // json.UnmarshalTypeError. If you want to unmarshal optional user data that might be null, use *User
84+ // instead of User.
7985func (u * User ) UnmarshalJSON (data []byte ) error {
86+ // Special handling here for a null value - json.Unmarshal will normally treat a null exactly like
87+ // "{}" when unmarshaling a struct. We don't want that, because it will produce a misleading
88+ // "missing key" error further down. Instead, just treat it as an invalid type.
89+ if string (data ) == "null" {
90+ return & json.UnmarshalTypeError {Value : string (data ), Type : reflect .TypeOf (u )}
91+ }
8092 var ufs userForDeserialization
8193 if err := json .Unmarshal (data , & ufs ); err != nil {
8294 return err
8395 }
8496 if ! ufs .Key .IsDefined () {
85- return errMissingKey
97+ return ErrMissingKey ()
8698 }
8799 * u = User {
88100 key : ufs .Key .StringValue (),
0 commit comments