diff --git a/go/model.go b/go/model.go index 6a5b794..62b06b4 100644 --- a/go/model.go +++ b/go/model.go @@ -96,7 +96,7 @@ type Item struct { ID string `json:"id"` ModelID string `json:"modelId"` Fields []Field `json:"fields"` - MetadataFields []Field `json:"metadataFields"` + MetadataFields []Field `json:"metadataFields,omitempty"` } func (i *Item) Clone() *Item { @@ -118,6 +118,14 @@ func (i Item) Field(id string) *Field { return nil } +func (i Item) MetadataField(id string) *Field { + f, ok := lo.Find(i.MetadataFields, func(f Field) bool { return f.ID == id }) + if ok { + return &f + } + return nil +} + func (i Item) FieldByKey(key string) *Field { f, ok := lo.Find(i.Fields, func(f Field) bool { return f.Key == key }) if ok { @@ -126,6 +134,14 @@ func (i Item) FieldByKey(key string) *Field { return nil } +func (i Item) MetadataFieldByKey(key string) *Field { + f, ok := lo.Find(i.MetadataFields, func(f Field) bool { return f.Key == key }) + if ok { + return &f + } + return nil +} + func (d Item) Unmarshal(i any) { if i == nil { return @@ -146,11 +162,13 @@ func (d Item) Unmarshal(i any) { for i := 0; i < t.NumField(); i++ { f := t.Field(i) tag := f.Tag.Get(tag) - key, _, _ := strings.Cut(tag, ",") + key, opts, _ := strings.Cut(tag, ",") if key == "" || key == "-" { continue } + isMetadata := strings.Contains(opts, ",metadata") + vf := v.FieldByName(f.Name) if !vf.CanSet() { continue @@ -163,7 +181,14 @@ func (d Item) Unmarshal(i any) { continue } - if itf := d.FieldByKey(key); itf != nil { + var itf *Field + if isMetadata { + itf = d.MetadataFieldByKey(key) + } else { + itf = d.FieldByKey(key) + } + + if itf != nil { if f.Type.Kind() == reflect.String { if itfv := itf.ValueString(); itfv != nil { vf.SetString(*itfv) @@ -210,11 +235,14 @@ func Marshal(i any, item *Item) { for i := 0; i < t.NumField(); i++ { f := t.Field(i) tag := f.Tag.Get(tag) - key, ty, _ := strings.Cut(tag, ",") + key, opts, _ := strings.Cut(tag, ",") if key == "" || key == "-" { continue } + isMetadata := strings.Contains(opts, ",metadata") + ty, _, _ := strings.Cut(opts, ",") + vf := v.FieldByName(f.Name) if key == "id" { ni.ID, _ = vf.Interface().(string) @@ -239,11 +267,17 @@ func Marshal(i any, item *Item) { } if i != nil { - ni.Fields = append(ni.Fields, Field{ + f := Field{ Key: key, Type: ty, Value: i, - }) + } + + if isMetadata { + ni.MetadataFields = append(ni.MetadataFields, f) + } else { + ni.Fields = append(ni.Fields, f) + } } } diff --git a/go/model_test.go b/go/model_test.go index ff67835..b5c1e62 100644 --- a/go/model_test.go +++ b/go/model_test.go @@ -16,6 +16,7 @@ func TestItem_Unmarshal(t *testing.T) { BBB []string `cms:"bbb"` CCC []str `cms:"ccc"` DDD map[string]any `cms:"ddd"` + EEE string `cms:"eee,,metadata"` } s := S{} @@ -27,6 +28,9 @@ func TestItem_Unmarshal(t *testing.T) { {Key: "ccc", Value: []string{"a", "b"}}, {Key: "ddd", Value: map[string]any{"a": "b"}}, }, + MetadataFields: []Field{ + {Key: "eee", Value: "xxx"}, + }, }.Unmarshal(&s) assert.Equal(t, S{ ID: "xxx", @@ -34,6 +38,7 @@ func TestItem_Unmarshal(t *testing.T) { BBB: []string{"ccc", "bbb"}, CCC: []str{"a", "b"}, DDD: map[string]any{"a": "b"}, + EEE: "xxx", }, s) // no panic @@ -51,6 +56,7 @@ func TestMarshal(t *testing.T) { CCC str `cms:"ccc"` DDD []str `cms:"ddd"` EEE string `cms:"eee,text"` + FFF string `cms:"fff,text,metadata"` } s := S{ ID: "xxx", @@ -58,6 +64,7 @@ func TestMarshal(t *testing.T) { BBB: []string{"ccc", "bbb"}, CCC: str("x"), DDD: []str{"1", "2"}, + FFF: "fff", } i := &Item{ ID: "xxx", @@ -68,6 +75,9 @@ func TestMarshal(t *testing.T) { {Key: "ddd", Type: "", Value: []string{"1", "2"}}, // no field for eee }, + MetadataFields: []Field{ + {Key: "fff", Type: "text", Value: "fff"}, + }, } item := &Item{} @@ -102,6 +112,23 @@ func TestItem_Field(t *testing.T) { }.Field("ccc")) } +func TestItem_MetadataField(t *testing.T) { + assert.Equal(t, &Field{ + ID: "bbb", Value: "ccc", Type: "string", + }, Item{ + MetadataFields: []Field{ + {ID: "aaa", Value: "bbb", Type: "string"}, + {ID: "bbb", Value: "ccc", Type: "string"}, + }, + }.MetadataField("bbb")) + assert.Nil(t, Item{ + MetadataFields: []Field{ + {ID: "aaa", Key: "bbb", Type: "string"}, + {ID: "bbb", Key: "ccc", Type: "string"}, + }, + }.MetadataField("ccc")) +} + func TestItem_FieldByKey(t *testing.T) { assert.Equal(t, &Field{ ID: "bbb", Key: "ccc", Type: "string", @@ -119,6 +146,23 @@ func TestItem_FieldByKey(t *testing.T) { }.FieldByKey("bbb")) } +func TestItem_MetadataFieldByKey(t *testing.T) { + assert.Equal(t, &Field{ + ID: "bbb", Key: "ccc", Type: "string", + }, Item{ + MetadataFields: []Field{ + {ID: "aaa", Key: "bbb", Type: "string"}, + {ID: "bbb", Key: "ccc", Type: "string"}, + }, + }.MetadataFieldByKey("ccc")) + assert.Nil(t, Item{ + MetadataFields: []Field{ + {ID: "aaa", Key: "aaa", Type: "string"}, + {ID: "bbb", Key: "ccc", Type: "string"}, + }, + }.MetadataFieldByKey("bbb")) +} + func TestField_ValueString(t *testing.T) { assert.Equal(t, lo.ToPtr("ccc"), (&Field{ Value: "ccc",