bool.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package null
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "reflect"
  8. )
  9. // Bool is a nullable bool.
  10. // It does not consider false values to be null.
  11. // It will decode to null, not false, if null.
  12. type Bool struct {
  13. sql.NullBool
  14. }
  15. // NewBool creates a new Bool
  16. func NewBool(b bool, valid bool) Bool {
  17. return Bool{
  18. NullBool: sql.NullBool{
  19. Bool: b,
  20. Valid: valid,
  21. },
  22. }
  23. }
  24. // BoolFrom creates a new Bool that will always be valid.
  25. func BoolFrom(b bool) Bool {
  26. return NewBool(b, true)
  27. }
  28. // BoolFromPtr creates a new Bool that will be null if f is nil.
  29. func BoolFromPtr(b *bool) Bool {
  30. if b == nil {
  31. return NewBool(false, false)
  32. }
  33. return NewBool(*b, true)
  34. }
  35. // UnmarshalJSON implements json.Unmarshaler.
  36. // It supports number and null input.
  37. // 0 will not be considered a null Bool.
  38. // It also supports unmarshalling a sql.NullBool.
  39. func (b *Bool) UnmarshalJSON(data []byte) error {
  40. var err error
  41. var v interface{}
  42. if err = json.Unmarshal(data, &v); err != nil {
  43. return err
  44. }
  45. switch x := v.(type) {
  46. case bool:
  47. b.Bool = x
  48. case map[string]interface{}:
  49. err = json.Unmarshal(data, &b.NullBool)
  50. case nil:
  51. b.Valid = false
  52. return nil
  53. default:
  54. err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Bool", reflect.TypeOf(v).Name())
  55. }
  56. b.Valid = err == nil
  57. return err
  58. }
  59. // UnmarshalText implements encoding.TextUnmarshaler.
  60. // It will unmarshal to a null Bool if the input is a blank or not an integer.
  61. // It will return an error if the input is not an integer, blank, or "null".
  62. func (b *Bool) UnmarshalText(text []byte) error {
  63. str := string(text)
  64. switch str {
  65. case "", "null":
  66. b.Valid = false
  67. return nil
  68. case "true":
  69. b.Bool = true
  70. case "false":
  71. b.Bool = false
  72. default:
  73. b.Valid = false
  74. return errors.New("invalid input:" + str)
  75. }
  76. b.Valid = true
  77. return nil
  78. }
  79. // MarshalJSON implements json.Marshaler.
  80. // It will encode null if this Bool is null.
  81. func (b Bool) MarshalJSON() ([]byte, error) {
  82. if !b.Valid {
  83. return []byte("null"), nil
  84. }
  85. if !b.Bool {
  86. return []byte("false"), nil
  87. }
  88. return []byte("true"), nil
  89. }
  90. // MarshalText implements encoding.TextMarshaler.
  91. // It will encode a blank string if this Bool is null.
  92. func (b Bool) MarshalText() ([]byte, error) {
  93. if !b.Valid {
  94. return []byte{}, nil
  95. }
  96. if !b.Bool {
  97. return []byte("false"), nil
  98. }
  99. return []byte("true"), nil
  100. }
  101. // SetValid changes this Bool's value and also sets it to be non-null.
  102. func (b *Bool) SetValid(v bool) {
  103. b.Bool = v
  104. b.Valid = true
  105. }
  106. // Ptr returns a pointer to this Bool's value, or a nil pointer if this Bool is null.
  107. func (b Bool) Ptr() *bool {
  108. if !b.Valid {
  109. return nil
  110. }
  111. return &b.Bool
  112. }
  113. // IsZero returns true for invalid Bools, for future omitempty support (Go 1.4?)
  114. // A non-null Bool with a 0 value will not be considered zero.
  115. func (b Bool) IsZero() bool {
  116. return !b.Valid
  117. }