2016-04-13 182 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 
相关问题