Поле 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"]

Go Playground


Если поле 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