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