Repository: zeromicro/go-zero
Pull request #3521 (2023-08-27 07:54:24)

feat: support json:"-" in mapping

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/zeromicro/go-zero/pull/3521?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#3521](https://app.codecov.io/gh/zeromicro/go-zero/pull/3521?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (de0f7e1) into [master](https://app.codecov.io/gh/zeromicro/go-zero/commit/7bbe7de05fdbee41dd0a43283c22fbf7e4ed31c4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (7bbe7de) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.


| [Files Changed](https://app.codecov.io/gh/zeromicro/go-zero/pull/3521?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [core/mapping/unmarshaler.go](https://app.codecov.io/gh/zeromicro/go-zero/pull/3521?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-Y29yZS9tYXBwaW5nL3VubWFyc2hhbGVyLmdv) | `96.44% <100.00%> (+0.02%)` | :arrow_up: |

... and [2 files with indirect coverage changes](https://app.codecov.io/gh/zeromicro/go-zero/pull/3521/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)


Patch:
diff --git a/core/mapping/unmarshaler.go b/core/mapping/unmarshaler.go
index 4a1129b6..c0912e9d 100644
--- a/core/mapping/unmarshaler.go
+++ b/core/mapping/unmarshaler.go
@@ -20,6 +20,7 @@ import (
 const (
 	defaultKeyName = "key"
 	delimiter      = '.'
+	ignoreKey      = "-"
 )
 
 var (
@@ -437,6 +438,10 @@ func (u *Unmarshaler) processAnonymousField(field reflect.StructField, value ref
 		return err
 	}
 
+	if key == ignoreKey {
+		return nil
+	}
+
 	if options.optional() {
 		return u.processAnonymousFieldOptional(field, value, key, m, fullName)
 	}
@@ -724,6 +729,10 @@ func (u *Unmarshaler) processNamedField(field reflect.StructField, value reflect
 		return err
 	}
 
+	if key == ignoreKey {
+		return nil
+	}
+
 	fullName = join(fullName, key)
 	if opts != nil && len(opts.EnvVar) > 0 {
 		envVal := proc.Env(opts.EnvVar)


Test patch:
diff --git a/core/mapping/unmarshaler_test.go b/core/mapping/unmarshaler_test.go
index f89ffb52..2e0e423d 100644
--- a/core/mapping/unmarshaler_test.go
+++ b/core/mapping/unmarshaler_test.go
@@ -5107,6 +5107,117 @@ func TestUnmarshalWithOpaqueKeys(t *testing.T) {
 	}
 }
 
+func TestUnmarshalWithIgnoreFields(t *testing.T) {
+	type (
+		Foo struct {
+			Value        string
+			IgnoreString string `json:"-"`
+			IgnoreInt    int    `json:"-"`
+		}
+
+		Bar struct {
+			Foo1 Foo
+			Foo2 *Foo
+			Foo3 []Foo
+			Foo4 []*Foo
+			Foo5 map[string]Foo
+			Foo6 map[string]Foo
+		}
+
+		Bar1 struct {
+			Foo `json:"-"`
+		}
+
+		Bar2 struct {
+			*Foo `json:"-"`
+		}
+	)
+
+	var bar Bar
+	unmarshaler := NewUnmarshaler(jsonTagKey)
+	if assert.NoError(t, unmarshaler.Unmarshal(map[string]any{
+		"Foo1": map[string]any{
+			"Value":        "foo",
+			"IgnoreString": "any",
+			"IgnoreInt":    2,
+		},
+		"Foo2": map[string]any{
+			"Value":        "foo",
+			"IgnoreString": "any",
+			"IgnoreInt":    2,
+		},
+		"Foo3": []map[string]any{
+			{
+				"Value":        "foo",
+				"IgnoreString": "any",
+				"IgnoreInt":    2,
+			},
+		},
+		"Foo4": []map[string]any{
+			{
+				"Value":        "foo",
+				"IgnoreString": "any",
+				"IgnoreInt":    2,
+			},
+		},
+		"Foo5": map[string]any{
+			"key": map[string]any{
+				"Value":        "foo",
+				"IgnoreString": "any",
+				"IgnoreInt":    2,
+			},
+		},
+		"Foo6": map[string]any{
+			"key": map[string]any{
+				"Value":        "foo",
+				"IgnoreString": "any",
+				"IgnoreInt":    2,
+			},
+		},
+	}, &bar)) {
+		assert.Equal(t, "foo", bar.Foo1.Value)
+		assert.Empty(t, bar.Foo1.IgnoreString)
+		assert.Equal(t, 0, bar.Foo1.IgnoreInt)
+		assert.Equal(t, "foo", bar.Foo2.Value)
+		assert.Empty(t, bar.Foo2.IgnoreString)
+		assert.Equal(t, 0, bar.Foo2.IgnoreInt)
+		assert.Equal(t, "foo", bar.Foo3[0].Value)
+		assert.Empty(t, bar.Foo3[0].IgnoreString)
+		assert.Equal(t, 0, bar.Foo3[0].IgnoreInt)
+		assert.Equal(t, "foo", bar.Foo4[0].Value)
+		assert.Empty(t, bar.Foo4[0].IgnoreString)
+		assert.Equal(t, 0, bar.Foo4[0].IgnoreInt)
+		assert.Equal(t, "foo", bar.Foo5["key"].Value)
+		assert.Empty(t, bar.Foo5["key"].IgnoreString)
+		assert.Equal(t, 0, bar.Foo5["key"].IgnoreInt)
+		assert.Equal(t, "foo", bar.Foo6["key"].Value)
+		assert.Empty(t, bar.Foo6["key"].IgnoreString)
+		assert.Equal(t, 0, bar.Foo6["key"].IgnoreInt)
+	}
+
+	var bar1 Bar1
+	if assert.NoError(t, unmarshaler.Unmarshal(map[string]any{
+		"Value":        "foo",
+		"IgnoreString": "any",
+		"IgnoreInt":    2,
+	}, &bar1)) {
+		assert.Empty(t, bar1.Value)
+		assert.Empty(t, bar1.IgnoreString)
+		assert.Equal(t, 0, bar1.IgnoreInt)
+	}
+
+	var bar2 Bar1
+	if assert.NoError(t, unmarshaler.Unmarshal(map[string]any{
+		"Value":        "foo",
+		"IgnoreString": "any",
+		"IgnoreInt":    2,
+	}, &bar2)) {
+		assert.Empty(t, bar2.Value)
+		assert.Empty(t, bar2.IgnoreString)
+		assert.Equal(t, 0, bar2.IgnoreInt)
+	}
+}
+
 func BenchmarkDefaultValue(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		var a struct {