Как мне хорошо работать со значениями SQL NULL и JSON в Golang?
Go типа как Int64
а также String
не может хранить нулевые значения, поэтому я обнаружил, что могу использовать sql.NullInt64 и sql.NullString для этого.
Но когда я использую их в Struct и генерирую JSON из Struct с помощью пакета json, формат отличается от того, когда я использую обычный Int64
а также String
типы.
JSON имеет дополнительный уровень, потому что sql.Null*** также является Struct.
Есть хороший обходной путь для этого, или я не должен использовать NULL в моей базе данных SQL?
2 ответа
Типы как sql.NullInt64
не реализуйте никакой специальной обработки для маршалинга или демаршалинга JSON, поэтому применяются правила по умолчанию. Поскольку тип является структурой, он маршалируется как объект с его полями в качестве атрибутов.
Одним из способов обойти это является создание собственного типа, который реализует json.Marshaller
/ json.Unmarshaler
интерфейсы. Встраивая sql.NullInt64
типа, мы получаем методы SQL бесплатно. Что-то вроде этого:
type JsonNullInt64 struct {
sql.NullInt64
}
func (v JsonNullInt64) MarshalJSON() ([]byte, error) {
if v.Valid {
return json.Marshal(v.Int64)
} else {
return json.Marshal(nil)
}
}
func (v *JsonNullInt64) UnmarshalJSON(data []byte) error {
// Unmarshalling into a pointer will let us detect null
var x *int64
if err := json.Unmarshal(data, &x); err != nil {
return err
}
if x != nil {
v.Valid = true
v.Int64 = *x
} else {
v.Valid = false
}
return nil
}
Если вы используете этот тип вместо sql.NullInt64
, это должно быть закодировано, как вы ожидаете.
Вы можете проверить этот пример здесь: http://play.golang.org/p/zFESxLcd-c
Если вы используете пакет null.v3, вам не нужно реализовывать какие-либо методы маршала или демаршала. Это надмножество структур sql.Null и, вероятно, то, что вы хотите.
package main
import "gopkg.in/guregu/null.v3"
type Person struct {
Name string `json:"id"`
Age int `json:"age"`
NickName null.String `json:"nickname"` // Optional
}
Если вы хотите увидеть полноценный веб-сервер Golang, который использует sqlite, nulls и json, вы можете обратиться к этой сути.