Поле JSON установлено на ноль против поля, которого нет
Есть ли способ, в golang, увидеть, могу ли я отличить поле json от значения null от поля json, не находящегося там, когда он не привязан к структуре? Потому что оба устанавливают значение в struct равным nil, но мне нужно знать, было ли это поле для начала, и чтобы убедиться, что кто-то установил его в null.
{
"somefield1":"somevalue1",
"somefield2":null
}
VS
{
"somefield1":"somevalue1",
}
Оба jsons будут равны нулю, если они не будут объединены в структуру.
Любые полезные ресурсы будут очень благодарны!
Ответы
Ответ 1
Используйте json.RawMessage
чтобы "задержать" процесс json.RawMessage
чтобы определить необработанный байт, прежде чем принять решение:
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
Ответ 2
Если вы размонтируете объект в интерфейсе карты [string] {}, вы можете просто проверить, есть ли там поле
type unMarshalledObject map[string]interface{}
json.Unmarshall(input, unMarshhaledObject)
_, ok := unMarshalledObject["somefield2"]
Перейти на площадку
Ответ 3
Хороший вопрос.
Я считаю, что вы можете использовать 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
Ответ 4
Если поле struct является указателем, JSON-декодер будет выделять новую переменную, если это поле присутствует или оставить его нулевым, если нет. Поэтому я предлагаю использовать указатели.
type Data struct {
StrField *string
IntField *int
}
...
if data.StrField != nil {
handle(*data.StrField)
}
Ответ 5
Используя 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