Поле Golang-JSON установлено в null vs поле не существует
есть ли способ, в golang, чтобы увидеть, если я могу отличить поле JSON быть установлено в null против поля в JSON не был там, когда неупорядоченными в структуру? Потому что оба значения в структуре равны нулю, но мне нужно знать, было ли поле для начала, и посмотреть, установил ли кто-то его значение null.
{
"somefield1":"somevalue1",
"somefield2":null
}
VS
{
"somefield1":"somevalue1",
}
Как jsons будет nil при неупорядоченными в структуру. Любые полезные ресурсы будут очень оценены!
5 ответов
использовать json.RawMessage
чтобы "задержать" процесс unmarshaling, чтобы определить необработанный байт, прежде чем решить что-то сделать:
var data = []byte(`{
"somefield1":"somevalue1",
"somefield2": null
}`)
type Data struct {
SomeField1 string
SomeField2 json.RawMessage
}
func main() {
d := &Data{}
_ = json.Unmarshal(data, &d)
fmt.Println(d.SomeField1)
if len(d.SomeField2) > 0 {
if string(d.SomeField2) == "null" {
fmt.Println("somefield2 is there but null")
} else {
fmt.Println("somefield2 is there and not null")
// Do something with the data
}
} else {
fmt.Println("somefield2 doesn't exist")
}
}
смотрите площадку https://play.golang.org/p/Wganpf4sbO
хороший вопрос.
Я считаю, что вы можете использовать https://golang.org/pkg/encoding/json/#RawMessage как:
type MyMessage struct {
somefield1 string
somefield2 json.RawMessage
}
поэтому после unmarshalling вы должны иметь []byte("null")
в случае null
и nil
если отсутствует.
вот код игровой площадки:https://play.golang.org/p/UW8L68K068
Если вы unmarshall объект в интерфейс map[string] {}, то вы можете просто проверить, есть ли поле
type unMarshalledObject map[string]interface{}
json.Unmarshall(input, unMarshhaledObject)
_, ok := unMarshalledObject["somefield2"]
Если поле struct является указателем, декодер JSON выделит новую переменную, если поле присутствует, или оставит ее нулевой, если нет. Поэтому я предлагаю использовать указатели.
type Data struct {
StrField *string
IntField *int
}
...
if data.StrField != nil {
handle(*data.StrField)
}
С помощью github.com/golang/protobuf/ptypes/struct
и jsonpb github.com/golang/protobuf/jsonpb
, вы можете сделать так:
func TestFunTest(t *testing.T) {
p := &pb.KnownTypes{}
e := UnmarshalString(`{"val":null}`, p)
fmt.Println(e, p)
p = &pb.KnownTypes{}
e = UnmarshalString(`{"val":1}`, p)
fmt.Println(e, p)
p = &pb.KnownTypes{}
e = UnmarshalString(`{"val":"string"}`, p)
fmt.Println(e, p)
p = &pb.KnownTypes{}
e = UnmarshalString(`{}`, p)
fmt.Println(e, p)
}
выход:
[ `go test -test.run="^TestFunTest$"` | done: 1.275431416s ]
<nil> val:<null_value:NULL_VALUE >
<nil> val:<number_value:1 >
<nil> val:<string_value:"string" >
<nil>
PASS