Skip to content

Commit

Permalink
Fix Unmarshalling JSON containing list elements so that we have updat…
Browse files Browse the repository at this point in the history
…e semantics. (#837)

Currently it's always doing replace. Add missing coverage.
  • Loading branch information
wenovus authored May 18, 2023
1 parent f59f391 commit cbef8ea
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
79 changes: 79 additions & 0 deletions ytypes/gnmi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,85 @@ func TestUnmarshalSetRequest(t *testing.T) {
},
},
},
}, {
desc: "updates to a struct containing a non-empty list",
inSchema: &Schema{
Root: &ContainerStruct1{
StructKeyList: map[string]*ListElemStruct1{
"forty-two": {
Key1: ygot.String("forty-two"),
Outer: &OuterContainerType1{
Inner: &InnerContainerType1{
Int32LeafName: ygot.Int32(43),
Int32LeafListName: []int32{100},
StringLeafName: ygot.String("bear"),
},
},
},
"forty-three": {
Key1: ygot.String("forty-three"),
Outer: &OuterContainerType1{
Inner: &InnerContainerType1{
Int32LeafName: ygot.Int32(43),
Int32LeafListName: []int32{100},
StringLeafName: ygot.String("bear"),
},
},
},
},
},
SchemaTree: map[string]*yang.Entry{
"ContainerStruct1": containerWithStringKey(),
},
},
inReq: &gpb.SetRequest{
Prefix: &gpb.Path{},
Update: []*gpb.Update{{
Path: mustPath("/"),
Val: &gpb.TypedValue{Value: &gpb.TypedValue_JsonIetfVal{
JsonIetfVal: []byte(`
{
"config": {
"simple-key-list": [
{
"key1": "forty-two",
"outer": {
"inner": {
"int32-leaf-list": [42]
}
}
}
]
}
}
`),
}},
}},
},
want: &ContainerStruct1{
StructKeyList: map[string]*ListElemStruct1{
"forty-two": {
Key1: ygot.String("forty-two"),
Outer: &OuterContainerType1{
Inner: &InnerContainerType1{
Int32LeafName: ygot.Int32(43),
Int32LeafListName: []int32{42},
StringLeafName: ygot.String("bear"),
},
},
},
"forty-three": {
Key1: ygot.String("forty-three"),
Outer: &OuterContainerType1{
Inner: &InnerContainerType1{
Int32LeafName: ygot.Int32(43),
Int32LeafListName: []int32{100},
StringLeafName: ygot.String("bear"),
},
},
},
},
},
}, {
desc: "updates of invalid paths to non-empty struct with IgnoreExtraFields",
inSchema: &Schema{
Expand Down
14 changes: 13 additions & 1 deletion ytypes/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,19 @@ func unmarshalList(schema *yang.Entry, parent interface{}, jsonList interface{},
if err != nil {
return err
}
err = util.InsertIntoMap(parent, newKey.Interface(), newVal.Interface())
// First try to get the existing element.
// If it doesn't exist, then use the new one in order
// to have update, and not replace semantics.
val := reflect.ValueOf(parent).MapIndex(newKey)
if !val.IsValid() || val.IsZero() {
val = newVal
} else {
if err := unmarshalStruct(schema, val.Interface(), jt, enc, opts...); err != nil {
return err
}
}

err = util.InsertIntoMap(parent, newKey.Interface(), val.Interface())
case util.IsTypeSlicePtr(t):
err = util.InsertIntoSlice(parent, newVal.Interface())
default:
Expand Down

0 comments on commit cbef8ea

Please sign in to comment.