From 8702425d0e9b76ed7a9efa2e5b7ffcf6556b7807 Mon Sep 17 00:00:00 2001 From: Michael Weibel Date: Wed, 6 Mar 2024 08:05:23 +0100 Subject: [PATCH] fix: support string tag opt fixes #36 --- sheriff.go | 15 +++++++++++++++ sheriff_test.go | 23 +++++++++++++++++++++++ tags.go | 16 +++++----------- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/sheriff.go b/sheriff.go index fb12667..4ac7fa0 100644 --- a/sheriff.go +++ b/sheriff.go @@ -106,6 +106,18 @@ func Marshal(options *Options, data interface{}) (interface{}, error) { continue } + quoted := false + if jsonOpts.Contains("string") { + switch val.Kind() { + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, + reflect.Float32, reflect.Float64, + reflect.String: + quoted = true + } + } + // if there is an anonymous field which is a struct // we want the childs exposed at the toplevel to be // consistent with the embedded json marshaller @@ -179,6 +191,9 @@ func Marshal(options *Options, data interface{}) (interface{}, error) { if err != nil { return nil, err } + if quoted { + v = fmt.Sprintf("%v", v) + } // when a composition field we want to bring the child // nodes to the top diff --git a/sheriff_test.go b/sheriff_test.go index 1cf5b66..3dcd937 100644 --- a/sheriff_test.go +++ b/sheriff_test.go @@ -754,3 +754,26 @@ func TestMarshal_NilPointer(t *testing.T) { assert.Nil(t, v) assert.NoError(t, err) } + +func TestMarshal_User(t *testing.T) { + type JsonStringTag struct { + Test int64 `json:"test,string"` + TestB bool `json:"testb,string"` + TestF float64 `json:"testf,string"` + TestS string `json:"tests,string"` + } + j := JsonStringTag{ + Test: 12, + TestB: true, + TestF: 12.0, + TestS: "test", + } + + v, err := Marshal(&Options{}, j) + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"test": "12", "testb": "true", "testf": "12", "tests": "test"}, v) + + d, err := json.Marshal(j) + assert.NoError(t, err) + assert.Equal(t, `{"test":"12","testb":"true","testf":"12","tests":"\"test\""}`, string(d)) +} diff --git a/tags.go b/tags.go index a6fa0dd..0a618c5 100644 --- a/tags.go +++ b/tags.go @@ -13,10 +13,8 @@ type tagOptions string // parseTag splits a struct field's json tag into its name and // comma-separated options. func parseTag(tag string) (string, tagOptions) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tagOptions(tag[idx+1:]) - } - return tag, tagOptions("") + tag, opt, _ := strings.Cut(tag, ",") + return tag, tagOptions(opt) } // Contains reports whether a comma-separated list of options @@ -28,15 +26,11 @@ func (o tagOptions) Contains(optionName string) bool { } s := string(o) for s != "" { - var next string - i := strings.Index(s, ",") - if i >= 0 { - s, next = s[:i], s[i+1:] - } - if s == optionName { + var name string + name, s, _ = strings.Cut(s, ",") + if name == optionName { return true } - s = next } return false }