diff --git a/README.MD b/README.MD index e1e9960cf..4dfff03b5 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,6 @@ # GoFrame -[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories) +[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf) [![Build Status](https://travis-ci.org/gogf/gf.svg?branch=master)](https://travis-ci.org/gogf/gf) [![Go Report](https://goreportcard.com/badge/github.com/gogf/gf?v=1)](https://goreportcard.com/report/github.com/gogf/gf) [![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf/branch/master) diff --git a/README_ZH.MD b/README_ZH.MD index 6b7bc074a..ed4bbf502 100644 --- a/README_ZH.MD +++ b/README_ZH.MD @@ -1,5 +1,5 @@ # GoFrame -[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories) +[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf) [![Build Status](https://travis-ci.org/gogf/gf.svg?branch=master)](https://travis-ci.org/gogf/gf) [![Go Report](https://goreportcard.com/badge/github.com/gogf/gf?v=1)](https://goreportcard.com/report/github.com/gogf/gf) [![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf/branch/master) diff --git a/container/garray/garray_normal_any.go b/container/garray/garray_normal_any.go index 23e576f3b..475901d22 100644 --- a/container/garray/garray_normal_any.go +++ b/container/garray/garray_normal_any.go @@ -10,6 +10,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/gogf/gf/internal/empty" "github.com/gogf/gf/text/gstr" "math" "sort" @@ -735,3 +736,32 @@ func (a *Array) UnmarshalValue(value interface{}) error { } return nil } + +// FilterNil removes all nil value of the array. +func (a *Array) FilterNil() *Array { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if empty.IsNil(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + i++ + } + } + return a +} + +// FilterEmpty removes all empty value of the array. +// Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. +func (a *Array) FilterEmpty() *Array { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if empty.IsEmpty(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + i++ + } + } + return a +} diff --git a/container/garray/garray_normal_int.go b/container/garray/garray_normal_int.go index 86b589dc9..b4eacfe7d 100644 --- a/container/garray/garray_normal_int.go +++ b/container/garray/garray_normal_int.go @@ -716,3 +716,17 @@ func (a *IntArray) UnmarshalValue(value interface{}) error { } return nil } + +// FilterEmpty removes all zero value of the array. +func (a *IntArray) FilterEmpty() *IntArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if a.array[i] == 0 { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + i++ + } + } + return a +} diff --git a/container/garray/garray_normal_str.go b/container/garray/garray_normal_str.go index 9317aad0c..a587827c1 100644 --- a/container/garray/garray_normal_str.go +++ b/container/garray/garray_normal_str.go @@ -716,3 +716,17 @@ func (a *StrArray) UnmarshalValue(value interface{}) error { } return nil } + +// FilterEmpty removes all empty string value of the array. +func (a *StrArray) FilterEmpty() *StrArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if a.array[i] == "" { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + i++ + } + } + return a +} diff --git a/container/garray/garray_sorted_any.go b/container/garray/garray_sorted_any.go index d2f3947f5..dd6c1690b 100644 --- a/container/garray/garray_sorted_any.go +++ b/container/garray/garray_sorted_any.go @@ -10,6 +10,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/gogf/gf/internal/empty" "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gutil" "math" @@ -686,3 +687,46 @@ func (a *SortedArray) UnmarshalValue(value interface{}) (err error) { } return err } + +// FilterNil removes all nil value of the array. +func (a *SortedArray) FilterNil() *SortedArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if empty.IsNil(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + for i := len(a.array) - 1; i >= 0; { + if empty.IsNil(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + return a +} + +// FilterEmpty removes all empty value of the array. +// Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. +func (a *SortedArray) FilterEmpty() *SortedArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if empty.IsEmpty(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + for i := len(a.array) - 1; i >= 0; { + if empty.IsEmpty(a.array[i]) { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + return a +} diff --git a/container/garray/garray_sorted_int.go b/container/garray/garray_sorted_int.go index b67f6f25c..4d469aa51 100644 --- a/container/garray/garray_sorted_int.go +++ b/container/garray/garray_sorted_int.go @@ -656,3 +656,24 @@ func (a *SortedIntArray) UnmarshalValue(value interface{}) (err error) { } return err } + +// FilterEmpty removes all zero value of the array. +func (a *SortedIntArray) FilterEmpty() *SortedIntArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if a.array[i] == 0 { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + for i := len(a.array) - 1; i >= 0; { + if a.array[i] == 0 { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + return a +} diff --git a/container/garray/garray_sorted_str.go b/container/garray/garray_sorted_str.go index ca691d171..1b8054c09 100644 --- a/container/garray/garray_sorted_str.go +++ b/container/garray/garray_sorted_str.go @@ -652,3 +652,24 @@ func (a *SortedStrArray) UnmarshalValue(value interface{}) (err error) { } return err } + +// FilterEmpty removes all empty string value of the array. +func (a *SortedStrArray) FilterEmpty() *SortedStrArray { + a.mu.Lock() + defer a.mu.Unlock() + for i := 0; i < len(a.array); { + if a.array[i] == "" { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + for i := len(a.array) - 1; i >= 0; { + if a.array[i] == "" { + a.array = append(a.array[:i], a.array[i+1:]...) + } else { + break + } + } + return a +} diff --git a/container/garray/garray_z_unit_normal_any_array_test.go b/container/garray/garray_z_unit_normal_any_array_test.go index 5d08275c6..10d002e99 100644 --- a/container/garray/garray_z_unit_normal_any_array_test.go +++ b/container/garray/garray_z_unit_normal_any_array_test.go @@ -540,3 +540,26 @@ func TestArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) }) } + +func TestArray_FilterNil(t *testing.T) { + gtest.Case(t, func() { + values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}} + array := garray.NewArrayFromCopy(values) + gtest.Assert(array.FilterNil().Slice(), values) + }) + gtest.Case(t, func() { + array := garray.NewArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}) + gtest.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4}) + }) +} + +func TestArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}) + gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) + gtest.Case(t, func() { + array := garray.NewArrayFrom(g.Slice{1, 2, 3, 4}) + gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) +} diff --git a/container/garray/garray_z_unit_normal_int_array_test.go b/container/garray/garray_z_unit_normal_int_array_test.go index 748d346eb..89ffea93b 100644 --- a/container/garray/garray_z_unit_normal_int_array_test.go +++ b/container/garray/garray_z_unit_normal_int_array_test.go @@ -575,3 +575,14 @@ func TestIntArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) }) } + +func TestIntArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0}) + gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4}) + }) + gtest.Case(t, func() { + array := garray.NewIntArrayFrom(g.SliceInt{1, 2, 3, 4}) + gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4}) + }) +} diff --git a/container/garray/garray_z_unit_normal_str_array_test.go b/container/garray/garray_z_unit_normal_str_array_test.go index 0d1bedaf6..4b1a976fb 100644 --- a/container/garray/garray_z_unit_normal_str_array_test.go +++ b/container/garray/garray_z_unit_normal_str_array_test.go @@ -578,3 +578,14 @@ func TestStrArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) }) } + +func TestStrArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewStrArrayFrom(g.SliceStr{"", "1", "2", "0"}) + gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2", "0"}) + }) + gtest.Case(t, func() { + array := garray.NewStrArrayFrom(g.SliceStr{"1", "2"}) + gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_any_array_test.go b/container/garray/garray_z_unit_sorted_any_array_test.go index f824f8d32..4fad67bf8 100644 --- a/container/garray/garray_z_unit_sorted_any_array_test.go +++ b/container/garray/garray_z_unit_sorted_any_array_test.go @@ -678,3 +678,26 @@ func TestSortedArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) }) } + +func TestSortedArray_FilterNil(t *testing.T) { + gtest.Case(t, func() { + values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}} + array := garray.NewSortedArrayFromCopy(values, gutil.ComparatorInt) + gtest.Assert(array.FilterNil().Slice(), g.Slice{0, "", g.Slice{}, 1, 2, 3, 4}) + }) + gtest.Case(t, func() { + array := garray.NewSortedArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}, gutil.ComparatorInt) + gtest.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4}) + }) +} + +func TestSortedArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewSortedArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}, gutil.ComparatorInt) + gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) + gtest.Case(t, func() { + array := garray.NewSortedArrayFrom(g.Slice{1, 2, 3, 4}, gutil.ComparatorInt) + gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_int_array_test.go b/container/garray/garray_z_unit_sorted_int_array_test.go index 47459759c..8a8d8a06a 100644 --- a/container/garray/garray_z_unit_sorted_int_array_test.go +++ b/container/garray/garray_z_unit_sorted_int_array_test.go @@ -559,3 +559,14 @@ func TestSortedIntArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) }) } + +func TestSortedIntArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewSortedIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0}) + gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4}) + }) + gtest.Case(t, func() { + array := garray.NewSortedIntArrayFrom(g.SliceInt{1, 2, 3, 4}) + gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_str_array_test.go b/container/garray/garray_z_unit_sorted_str_array_test.go index 2a9a6bbcf..a194cffcf 100644 --- a/container/garray/garray_z_unit_sorted_str_array_test.go +++ b/container/garray/garray_z_unit_sorted_str_array_test.go @@ -568,3 +568,14 @@ func TestSortedStrArray_UnmarshalValue(t *testing.T) { gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) }) } + +func TestSortedStrArray_FilterEmpty(t *testing.T) { + gtest.Case(t, func() { + array := garray.NewSortedStrArrayFrom(g.SliceStr{"", "1", "2", "0"}) + gtest.Assert(array.FilterEmpty(), g.SliceStr{"0", "1", "2"}) + }) + gtest.Case(t, func() { + array := garray.NewSortedStrArrayFrom(g.SliceStr{"1", "2"}) + gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"}) + }) +} diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index f42627fdc..d94260ba8 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -35,7 +35,7 @@ type apiIterator interface { Iterator(f func(key, value interface{}) bool) } -// apiInterfacesis the type assert api for Interfaces. +// apiInterfaces is the type assert api for Interfaces. type apiInterfaces interface { Interfaces() []interface{} } diff --git a/database/gdb/gdb_model.go b/database/gdb/gdb_model.go index f62600e41..aa7bf739c 100644 --- a/database/gdb/gdb_model.go +++ b/database/gdb/gdb_model.go @@ -10,6 +10,7 @@ import ( "database/sql" "errors" "fmt" + "github.com/gogf/gf/container/garray" "github.com/gogf/gf/container/gmap" "reflect" "time" @@ -243,6 +244,9 @@ func (m *Model) Fields(fields string) *Model { // FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. func (m *Model) FieldsEx(fields string) *Model { + if gstr.Contains(m.tables, " ") { + panic("function FieldsEx supports only single table operations") + } model := m.getModel() model.fieldsEx = fields fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) @@ -261,6 +265,47 @@ func (m *Model) FieldsEx(fields string) *Model { return model } +// FieldsStr retrieves and returns all fields from the table, joined with char ','. +// The optional parameter specifies the prefix for each field, eg: FieldsStr("u."). +func (m *Model) FieldsStr(prefix ...string) string { + prefixStr := "" + if len(prefix) > 0 { + prefixStr = prefix[0] + } + if m, err := m.db.TableFields(m.tables); err == nil { + fieldsArray := garray.NewStrArraySize(len(m), len(m)) + for _, field := range m { + fieldsArray.Set(field.Index, prefixStr+field.Name) + } + return fieldsArray.Join(",") + } + return "" +} + +// FieldsExStr retrieves and returns fields which are not in parameter from the table, +// joined with char ','. +// The parameter specifies the fields that are excluded. +// The optional parameter specifies the prefix for each field, eg: FieldsExStr("id", "u."). +func (m *Model) FieldsExStr(fields string, prefix ...string) string { + prefixStr := "" + if len(prefix) > 0 { + prefixStr = prefix[0] + } + if m, err := m.db.TableFields(m.tables); err == nil { + fieldsArray := garray.NewStrArraySize(len(m), len(m)) + fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) + for _, field := range m { + if fieldsExSet.Contains(field.Name) { + continue + } + fieldsArray.Set(field.Index, prefixStr+field.Name) + } + fieldsArray.FilterEmpty() + return fieldsArray.Join(",") + } + return "" +} + // Option adds extra operation option for the model. func (m *Model) Option(option int) *Model { model := m.getModel() @@ -283,6 +328,9 @@ func (m *Model) OmitEmpty() *Model { // Filter marks filtering the fields which does not exist in the fields of the operated table. func (m *Model) Filter() *Model { + if gstr.Contains(m.tables, " ") { + panic("function Filter supports only single table operations") + } model := m.getModel() model.filter = true return model diff --git a/database/gdb/gdb_mssql.go b/database/gdb/gdb_mssql.go index d7f815ad1..f838b7902 100644 --- a/database/gdb/gdb_mssql.go +++ b/database/gdb/gdb_mssql.go @@ -14,6 +14,7 @@ package gdb import ( "database/sql" "fmt" + "github.com/gogf/gf/text/gstr" "strconv" "strings" @@ -154,6 +155,10 @@ func (db *dbMssql) Tables(schema ...string) (tables []string, err error) { } func (db *dbMssql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { + table = gstr.Trim(table) + if gstr.Contains(table, " ") { + panic("function TableFields supports only single table operations") + } checkSchema := db.schema.Val() if len(schema) > 0 && schema[0] != "" { checkSchema = schema[0] diff --git a/database/gdb/gdb_oracle.go b/database/gdb/gdb_oracle.go index 278288091..23e79f121 100644 --- a/database/gdb/gdb_oracle.go +++ b/database/gdb/gdb_oracle.go @@ -15,6 +15,7 @@ import ( "database/sql" "errors" "fmt" + "github.com/gogf/gf/text/gstr" "reflect" "strconv" "strings" @@ -118,6 +119,10 @@ func (db *dbOracle) Tables(schema ...string) (tables []string, err error) { } func (db *dbOracle) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { + table = gstr.Trim(table) + if gstr.Contains(table, " ") { + panic("function TableFields supports only single table operations") + } checkSchema := db.schema.Val() if len(schema) > 0 && schema[0] != "" { checkSchema = schema[0] diff --git a/database/gdb/gdb_pgsql.go b/database/gdb/gdb_pgsql.go index 94cb1ccac..705edcb9f 100644 --- a/database/gdb/gdb_pgsql.go +++ b/database/gdb/gdb_pgsql.go @@ -14,6 +14,7 @@ package gdb import ( "database/sql" "fmt" + "github.com/gogf/gf/text/gstr" "strings" "github.com/gogf/gf/text/gregex" @@ -60,6 +61,10 @@ func (db *dbPgsql) Tables(schema ...string) (tables []string, err error) { } func (db *dbPgsql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { + table = gstr.Trim(table) + if gstr.Contains(table, " ") { + panic("function TableFields supports only single table operations") + } table, _ = gregex.ReplaceString("\"", "", table) checkSchema := db.schema.Val() if len(schema) > 0 && schema[0] != "" { diff --git a/database/gdb/gdb_sqlite.go b/database/gdb/gdb_sqlite.go index 09c5a9fec..b121953cc 100644 --- a/database/gdb/gdb_sqlite.go +++ b/database/gdb/gdb_sqlite.go @@ -12,6 +12,7 @@ package gdb import ( "database/sql" + "github.com/gogf/gf/text/gstr" ) type dbSqlite struct { @@ -43,6 +44,10 @@ func (db *dbSqlite) Tables(schema ...string) (tables []string, err error) { // TODO func (db *dbSqlite) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { + table = gstr.Trim(table) + if gstr.Contains(table, " ") { + panic("function TableFields supports only single table operations") + } return } diff --git a/database/gdb/gdb_structure.go b/database/gdb/gdb_structure.go index 03568c30e..cc34c9f80 100644 --- a/database/gdb/gdb_structure.go +++ b/database/gdb/gdb_structure.go @@ -141,11 +141,16 @@ func (bs *dbBase) Tables(schema ...string) (tables []string, err error) { } // TableFields retrieves and returns the fields of given table. +// // Note that it returns a map containing the field name and its corresponding fields. // As a map is unsorted, the TableField struct has a "Index" field marks its sequence in the fields. // // It's using cache feature to enhance the performance, which is never expired util the process restarts. func (bs *dbBase) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { + table = gstr.Trim(table) + if gstr.Contains(table, " ") { + panic("function TableFields supports only single table operations") + } checkSchema := bs.schema.Val() if len(schema) > 0 && schema[0] != "" { checkSchema = schema[0] diff --git a/database/gdb/gdb_unit_z_mysql_model_test.go b/database/gdb/gdb_unit_z_mysql_model_test.go index c0566626b..4f523a66b 100644 --- a/database/gdb/gdb_unit_z_mysql_model_test.go +++ b/database/gdb/gdb_unit_z_mysql_model_test.go @@ -1698,6 +1698,26 @@ func Test_Model_FieldsEx(t *testing.T) { }) } +func Test_Model_FieldsStr(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.Case(t, func() { + gtest.Assert(db.Table(table).FieldsStr(), "id,passport,password,nickname,create_time") + gtest.Assert(db.Table(table).FieldsStr("a."), "a.id,a.passport,a.password,a.nickname,a.create_time") + }) +} + +func Test_Model_FieldsExStr(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.Case(t, func() { + gtest.Assert(db.Table(table).FieldsExStr("create_time,nickname"), "id,passport,password") + gtest.Assert(db.Table(table).FieldsExStr("create_time,nickname", "a."), "a.id,a.passport,a.password") + }) +} + func Test_Model_Prefix(t *testing.T) { db := dbPrefix table := fmt.Sprintf(`%s_%d`, TABLE, gtime.TimestampNano()) diff --git a/util/gconv/gconv_map.go b/util/gconv/gconv_map.go index 11db8c7fe..edb1193b7 100644 --- a/util/gconv/gconv_map.go +++ b/util/gconv/gconv_map.go @@ -16,7 +16,7 @@ import ( "github.com/gogf/gf/internal/utilstr" ) -// apiMapStrAny is the interface support for package gmap. +// apiMapStrAny is the interface support for converting struct parameter to map. type apiMapStrAny interface { MapStrAny() map[string]interface{} } @@ -138,6 +138,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string] m[String(k.Interface())] = rv.MapIndex(k).Interface() } case reflect.Struct: + // Map converting interface check. if v, ok := value.(apiMapStrAny); ok { return v.MapStrAny() }