Skip to content

Commit cbef8ea

Browse files
authored
Fix Unmarshalling JSON containing list elements so that we have update semantics. (#837)
Currently it's always doing replace. Add missing coverage.
1 parent f59f391 commit cbef8ea

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

ytypes/gnmi_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,85 @@ func TestUnmarshalSetRequest(t *testing.T) {
102102
},
103103
},
104104
},
105+
}, {
106+
desc: "updates to a struct containing a non-empty list",
107+
inSchema: &Schema{
108+
Root: &ContainerStruct1{
109+
StructKeyList: map[string]*ListElemStruct1{
110+
"forty-two": {
111+
Key1: ygot.String("forty-two"),
112+
Outer: &OuterContainerType1{
113+
Inner: &InnerContainerType1{
114+
Int32LeafName: ygot.Int32(43),
115+
Int32LeafListName: []int32{100},
116+
StringLeafName: ygot.String("bear"),
117+
},
118+
},
119+
},
120+
"forty-three": {
121+
Key1: ygot.String("forty-three"),
122+
Outer: &OuterContainerType1{
123+
Inner: &InnerContainerType1{
124+
Int32LeafName: ygot.Int32(43),
125+
Int32LeafListName: []int32{100},
126+
StringLeafName: ygot.String("bear"),
127+
},
128+
},
129+
},
130+
},
131+
},
132+
SchemaTree: map[string]*yang.Entry{
133+
"ContainerStruct1": containerWithStringKey(),
134+
},
135+
},
136+
inReq: &gpb.SetRequest{
137+
Prefix: &gpb.Path{},
138+
Update: []*gpb.Update{{
139+
Path: mustPath("/"),
140+
Val: &gpb.TypedValue{Value: &gpb.TypedValue_JsonIetfVal{
141+
JsonIetfVal: []byte(`
142+
{
143+
"config": {
144+
"simple-key-list": [
145+
{
146+
"key1": "forty-two",
147+
"outer": {
148+
"inner": {
149+
"int32-leaf-list": [42]
150+
}
151+
}
152+
}
153+
]
154+
}
155+
}
156+
`),
157+
}},
158+
}},
159+
},
160+
want: &ContainerStruct1{
161+
StructKeyList: map[string]*ListElemStruct1{
162+
"forty-two": {
163+
Key1: ygot.String("forty-two"),
164+
Outer: &OuterContainerType1{
165+
Inner: &InnerContainerType1{
166+
Int32LeafName: ygot.Int32(43),
167+
Int32LeafListName: []int32{42},
168+
StringLeafName: ygot.String("bear"),
169+
},
170+
},
171+
},
172+
"forty-three": {
173+
Key1: ygot.String("forty-three"),
174+
Outer: &OuterContainerType1{
175+
Inner: &InnerContainerType1{
176+
Int32LeafName: ygot.Int32(43),
177+
Int32LeafListName: []int32{100},
178+
StringLeafName: ygot.String("bear"),
179+
},
180+
},
181+
},
182+
},
183+
},
105184
}, {
106185
desc: "updates of invalid paths to non-empty struct with IgnoreExtraFields",
107186
inSchema: &Schema{

ytypes/list.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,19 @@ func unmarshalList(schema *yang.Entry, parent interface{}, jsonList interface{},
342342
if err != nil {
343343
return err
344344
}
345-
err = util.InsertIntoMap(parent, newKey.Interface(), newVal.Interface())
345+
// First try to get the existing element.
346+
// If it doesn't exist, then use the new one in order
347+
// to have update, and not replace semantics.
348+
val := reflect.ValueOf(parent).MapIndex(newKey)
349+
if !val.IsValid() || val.IsZero() {
350+
val = newVal
351+
} else {
352+
if err := unmarshalStruct(schema, val.Interface(), jt, enc, opts...); err != nil {
353+
return err
354+
}
355+
}
356+
357+
err = util.InsertIntoMap(parent, newKey.Interface(), val.Interface())
346358
case util.IsTypeSlicePtr(t):
347359
err = util.InsertIntoSlice(parent, newVal.Interface())
348360
default:

0 commit comments

Comments
 (0)