diff --git a/core/mapping/unmarshaler_test.go b/core/mapping/unmarshaler_test.go index e4fd78fd2091..9619d5da3bdf 100644 --- a/core/mapping/unmarshaler_test.go +++ b/core/mapping/unmarshaler_test.go @@ -2991,6 +2991,97 @@ func TestUnmarshaler_InheritFromGrandparent(t *testing.T) { assert.Equal(t, "localhost:8080", s.Middle.Value.Discovery) } +func TestUnmarshaler_InheritSequence(t *testing.T) { + var testConf = []byte(` +Nacos: + NamespaceId: "123" +RpcConf: + Nacos: + NamespaceId: "456" + Name: hello +`) + + type ( + NacosConf struct { + NamespaceId string + } + + RpcConf struct { + Nacos NacosConf `json:",inherit"` + Name string + } + + Config1 struct { + RpcConf RpcConf + Nacos NacosConf + } + + Config2 struct { + RpcConf RpcConf + Nacos NacosConf + } + ) + + var c1 Config1 + assert.NoError(t, UnmarshalYamlBytes(testConf, &c1)) + assert.Equal(t, "123", c1.Nacos.NamespaceId) + assert.Equal(t, "456", c1.RpcConf.Nacos.NamespaceId) + + var c2 Config2 + assert.NoError(t, UnmarshalYamlBytes(testConf, &c2)) + assert.Equal(t, "123", c1.Nacos.NamespaceId) + assert.Equal(t, "456", c1.RpcConf.Nacos.NamespaceId) +} + +func TestUnmarshaler_InheritNested(t *testing.T) { + var testConf = []byte(` +Nacos: + Value1: "123" +Server: + Nacos: + Value2: "456" + Rpc: + Nacos: + Value3: "789" + Name: hello +`) + + type ( + NacosConf struct { + Value1 string `json:",optional"` + Value2 string `json:",optional"` + Value3 string `json:",optional"` + } + + RpcConf struct { + Nacos NacosConf `json:",inherit"` + Name string + } + + ServerConf struct { + Nacos NacosConf `json:",inherit"` + Rpc RpcConf + } + + Config struct { + Server ServerConf + Nacos NacosConf + } + ) + + var c Config + assert.NoError(t, UnmarshalYamlBytes(testConf, &c)) + assert.Equal(t, "123", c.Nacos.Value1) + assert.Empty(t, c.Nacos.Value2) + assert.Empty(t, c.Nacos.Value3) + assert.Equal(t, "123", c.Server.Nacos.Value1) + assert.Equal(t, "456", c.Server.Nacos.Value2) + assert.Empty(t, c.Nacos.Value3) + assert.Equal(t, "123", c.Server.Rpc.Nacos.Value1) + assert.Equal(t, "456", c.Server.Rpc.Nacos.Value2) + assert.Equal(t, "789", c.Server.Rpc.Nacos.Value3) +} + func TestUnmarshalValuer(t *testing.T) { unmarshaler := NewUnmarshaler(jsonTagKey) var foo string diff --git a/core/mapping/valuer.go b/core/mapping/valuer.go index e22c877fc8ee..8df2cc0995f3 100644 --- a/core/mapping/valuer.go +++ b/core/mapping/valuer.go @@ -70,21 +70,33 @@ func (rv recursiveValuer) Value(key string) (interface{}, bool) { return nil, false } - if vm, ok := val.(map[string]interface{}); ok { - if parent := rv.Parent(); parent != nil { - pv, pok := parent.Value(key) - if pok { - if pm, ok := pv.(map[string]interface{}); ok { - for k, v := range vm { - pm[k] = v - } - return pm, true - } - } + vm, ok := val.(map[string]interface{}) + if !ok { + return val, true + } + + parent := rv.Parent() + if parent == nil { + return val, true + } + + pv, ok := parent.Value(key) + if !ok { + return val, true + } + + pm, ok := pv.(map[string]interface{}) + if !ok { + return val, true + } + + for k, v := range pm { + if _, ok := vm[k]; !ok { + vm[k] = v } } - return val, true + return vm, true } // Parent get the parent valuer from rv.