diff --git a/datastore/load.go b/datastore/load.go index 86315019bbc..e00468cf1ac 100644 --- a/datastore/load.go +++ b/datastore/load.go @@ -161,6 +161,11 @@ func (l *propertyLoader) loadOneElement(codec fields.List, structValue reflect.V structValue = v } + if v.Kind() == reflect.Slice && p.Value == nil { + v.Set(reflect.Zero(v.Type())) + return "" + } + // If the element is a slice, we need to accommodate it. if v.Kind() == reflect.Slice && v.Type() != typeOfByteSlice { if l.m == nil { diff --git a/datastore/load_test.go b/datastore/load_test.go index ac9af8c9be5..c356119dc28 100644 --- a/datastore/load_test.go +++ b/datastore/load_test.go @@ -316,6 +316,18 @@ func TestLoadEntityNested(t *testing.T) { A: []Simple{{I: 3}, {I: 4}}, }, }, + { + desc: "nested simple with nil slice", + src: &pb.Entity{ + Properties: map[string]*pb.Value{ + "A": {ValueType: &pb.Value_NullValue{}}, + }, + }, + + want: &NestedSliceOfSimple{ + A: nil, + }, + }, { desc: "nested with multiple anonymous fields", src: &pb.Entity{ diff --git a/datastore/save.go b/datastore/save.go index 6925db5479a..2c3f79a062e 100644 --- a/datastore/save.go +++ b/datastore/save.go @@ -265,6 +265,11 @@ func (s structPLS) key(v reflect.Value) (*Key, error) { func saveSliceProperty(props *[]Property, name string, opts saveOpts, v reflect.Value) error { // Easy case: if the slice is empty, we're done. if v.Len() == 0 { + *props = append(*props, Property{ + Name: name, + Value: nil, + NoIndex: opts.noIndex, + }) return nil } // Work out the properties generated by the first element in the slice. This will