2016-04-13 124 views
7

有沒有一種方法,在golang中,看看我是否可以區分json字段設置爲null與json字段不在那裏時解組到一個結構?因爲兩者都將結構中的值設置爲nil,但我需要知道該字段是否在那裏開始,並查看是否有人將其設置爲null。當解組成一個結構Golang - JSON字段設置爲空vs字段不存在

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

VS

{ 
    "somefield1":"somevalue1", 
} 

兩個jsons將是零。 任何有用的資源將非常感激!

回答

6

使用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.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") 
    } 
} 

見操場https://play.golang.org/p/Wganpf4sbO

+0

對不起,我是Go的新手,我不確定,但是如果說SomeField2是「hello」,它會不會說這是空的? –

+1

不錯,需要一點編輯 - https://play.golang.org/p/UW8L68K068 –

+1

@AlexanderTrakhimenok感謝編輯過的評論。 – PieOhPah

2

如果解組對象成圖[字符串]接口{}那麼你可以只檢查一個字段是有

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

Go Playground

+2

使用的'地圖[字符串]接口{}',雖然有趣在這種情況下,這是一個矯枉過正的過度複雜化。 – PieOhPah

+0

同意@ pie-o-pah,這會隱藏somefield1的類型,但知道它的工作是非常有趣的。 –

0

如果struct字段是一個指針,那麼JSON解碼器將在該字段存在時分配新變量,否則將保留爲零。所以我建議使用指針。

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

通過使用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 
相關問題