2016-04-13 15 views
7

Gibt es einen Weg, in Golang, um zu sehen, wenn ich unterscheiden kann zwischen einem Json-Feld auf null vs ein Json-Feld nicht da sein, wenn unmarshalled in eine Struktur? Weil beide den Wert in der Struktur auf Null setzen, aber ich muss wissen, ob das Feld da war, um damit zu beginnen und um zu sehen, ob jemand es auf Null gesetzt hat.Golang - JSON-Feld auf Null gesetzt vs Feld nicht

{ 
    "somefield1":"somevalue1", 
    "somefield2":null 
} 

VS

{ 
    "somefield1":"somevalue1", 
} 

Beide jsons wird gleich Null, wenn sie in einem struct entordnet. Alle nützlichen Ressourcen werden sehr geschätzt!

Antwort

6

Verwenden json.RawMessage auf "Verzögerung" der Unmarshalling Prozess vor der Entscheidung, das rohe Byte, um zu bestimmen, etwas zu tun:

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.SomeField1) == "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") 
    } 
} 

Siehe den Spielplatz https://play.golang.org/p/Wganpf4sbO

+0

Sorry, ich bin ein Neuling zu gehen, und ich bin mir nicht sicher, aber würde nicht sagen, es ist null, wenn SomeField2 "Hallo" sagen? –

+1

Gute, brauche ein wenig bearbeiten - https://play.golang.org/p/UW8L68K068 –

+1

@AlexanderTrakhimenok danke für die Ausarbeitung bearbeitet wie kommentiert. – PieOhPah

2

Wenn Sie das Objekt in einer Karte [string] Schnittstelle entordnen {} dann überprüfen Sie können einfach, wenn ein Feld gibt es

type unMarshalledObject map[string]interface{} 
json.Unmarshall(input, unMarshhaledObject) 
_, ok := unMarshalledObject["somefield2"] 

Go Playground

+2

Die Verwendung von 'map [string] Schnittstelle {}', obwohl interessant ist in diesem Fall ein Overkill und übermäßig kompliziert. – PieOhPah

+0

Vereinbar mit @ pie-o-pah, dies würde den Typ von somefield1 verbergen, aber es ist sehr interessant zu wissen, dass es überhaupt funktioniert. –

0

Wenn das struct-Feld ein Zeiger ist, weist der JSON-Decoder eine neue Variable zu, wenn das Feld vorhanden ist, oder belassen es nicht, wenn nicht. Also schlage ich vor, Zeiger zu verwenden.

type Data struct { 
    StrField *string 
    IntField *int 
} 
... 
if data.StrField != nil { 
    handle(*data.StrField) 
} 
0

von github.com/golang/protobuf/ptypes/struct und jsonpb mit github.com/golang/protobuf/jsonpb, können Sie wie folgt tun:

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) 
} 

Ausgang:

[ `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 
Verwandte Themen