github.com/seeker-insurance/kit@v0.0.13/db/null/zero/string.go (about) 1 // Package zero contains SQL types that consider zero input and null input to be equivalent 2 // with convenient support for JSON and text marshaling. 3 // Types in this package will JSON marshal to their zero value, even if null. 4 // Use the null parent package if you don't want this. 5 package zero 6 7 import ( 8 "database/sql" 9 "encoding/json" 10 "fmt" 11 "reflect" 12 ) 13 14 // String is a nullable string. 15 // JSON marshals to a blank string if null. 16 // Considered null to SQL if zero. 17 type String struct { 18 sql.NullString 19 } 20 21 // NewString creates a new String 22 func NewString(s string, valid bool) String { 23 return String{ 24 NullString: sql.NullString{ 25 String: s, 26 Valid: valid, 27 }, 28 } 29 } 30 31 // StringFrom creates a new String that will be null if s is blank. 32 func StringFrom(s string) String { 33 return NewString(s, s != "") 34 } 35 36 // StringFromPtr creates a new String that be null if s is nil or blank. 37 // It will make s point to the String's value. 38 func StringFromPtr(s *string) String { 39 if s == nil { 40 return NewString("", false) 41 } 42 return NewString(*s, *s != "") 43 } 44 45 // UnmarshalJSON implements json.Unmarshaler. 46 // It supports string and null input. Blank string input produces a null String. 47 // It also supports unmarshalling a sql.NullString. 48 func (s *String) UnmarshalJSON(data []byte) error { 49 var err error 50 var v interface{} 51 if err = json.Unmarshal(data, &v); err != nil { 52 return err 53 } 54 switch x := v.(type) { 55 case string: 56 s.String = x 57 case map[string]interface{}: 58 err = json.Unmarshal(data, &s.NullString) 59 case nil: 60 s.Valid = false 61 return nil 62 default: 63 err = fmt.Errorf("json: cannot unmarshal %v into Go value of type zero.String", reflect.TypeOf(v).Name()) 64 } 65 s.Valid = (err == nil) && (s.String != "") 66 return err 67 } 68 69 // MarshalText implements encoding.TextMarshaler. 70 // It will encode a blank string when this String is null. 71 func (s String) MarshalText() ([]byte, error) { 72 if !s.Valid { 73 return []byte{}, nil 74 } 75 return []byte(s.String), nil 76 } 77 78 // UnmarshalText implements encoding.TextUnmarshaler. 79 // It will unmarshal to a null String if the input is a blank string. 80 func (s *String) UnmarshalText(text []byte) error { 81 s.String = string(text) 82 s.Valid = s.String != "" 83 return nil 84 } 85 86 // SetValid changes this String's value and also sets it to be non-null. 87 func (s *String) SetValid(v string) { 88 s.String = v 89 s.Valid = true 90 } 91 92 // Ptr returns a pointer to this String's value, or a nil pointer if this String is null. 93 func (s String) Ptr() *string { 94 if !s.Valid { 95 return nil 96 } 97 return &s.String 98 } 99 100 // IsZero returns true for null or empty strings, for potential future omitempty support. 101 func (s String) IsZero() bool { 102 return !s.Valid || s.String == "" 103 }