string.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. import (
  7. "database/sql"
  8. "encoding/json"
  9. "fmt"
  10. "reflect"
  11. )
  12. // String is a nullable string. It supports SQL and JSON serialization.
  13. // It will marshal to null if null. Blank string input will be considered null.
  14. type String struct {
  15. sql.NullString
  16. }
  17. // StringFrom creates a new String that will never be blank.
  18. func StringFrom(s string) String {
  19. return NewString(s, true)
  20. }
  21. // StringFromPtr creates a new String that be null if s is nil.
  22. func StringFromPtr(s *string) String {
  23. if s == nil {
  24. return NewString("", false)
  25. }
  26. return NewString(*s, true)
  27. }
  28. // NewString creates a new String
  29. func NewString(s string, valid bool) String {
  30. return String{
  31. NullString: sql.NullString{
  32. String: s,
  33. Valid: valid,
  34. },
  35. }
  36. }
  37. // UnmarshalJSON implements json.Unmarshaler.
  38. // It supports string and null input. Blank string input does not produce a null String.
  39. // It also supports unmarshalling a sql.NullString.
  40. func (s *String) UnmarshalJSON(data []byte) error {
  41. var err error
  42. var v interface{}
  43. if err = json.Unmarshal(data, &v); err != nil {
  44. return err
  45. }
  46. switch x := v.(type) {
  47. case string:
  48. s.String = x
  49. case map[string]interface{}:
  50. err = json.Unmarshal(data, &s.NullString)
  51. case nil:
  52. s.Valid = false
  53. return nil
  54. default:
  55. err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.String", reflect.TypeOf(v).Name())
  56. }
  57. s.Valid = err == nil
  58. return err
  59. }
  60. // MarshalJSON implements json.Marshaler.
  61. // It will encode null if this String is null.
  62. func (s String) MarshalJSON() ([]byte, error) {
  63. if !s.Valid {
  64. return []byte("null"), nil
  65. }
  66. return json.Marshal(s.String)
  67. }
  68. // MarshalText implements encoding.TextMarshaler.
  69. // It will encode a blank string when this String is null.
  70. func (s String) MarshalText() ([]byte, error) {
  71. if !s.Valid {
  72. return []byte{}, nil
  73. }
  74. return []byte(s.String), nil
  75. }
  76. // UnmarshalText implements encoding.TextUnmarshaler.
  77. // It will unmarshal to a null String if the input is a blank string.
  78. func (s *String) UnmarshalText(text []byte) error {
  79. s.String = string(text)
  80. s.Valid = s.String != ""
  81. return nil
  82. }
  83. // SetValid changes this String's value and also sets it to be non-null.
  84. func (s *String) SetValid(v string) {
  85. s.String = v
  86. s.Valid = true
  87. }
  88. // Ptr returns a pointer to this String's value, or a nil pointer if this String is null.
  89. func (s String) Ptr() *string {
  90. if !s.Valid {
  91. return nil
  92. }
  93. return &s.String
  94. }
  95. // IsZero returns true for null strings, for potential future omitempty support.
  96. func (s String) IsZero() bool {
  97. return !s.Valid
  98. }