diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index 0403ca55d..0e331426f 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -10,10 +10,21 @@ import ( "bytes" "fmt" "github.com/gogf/gf/v2/internal/structs" + "github.com/gogf/gf/v2/text/gstr" "reflect" "strings" ) +// iString is used for type assert api for String(). +type iString interface { + String() string +} + +// iMarshalJSON is the interface for custom Json marshaling. +type iMarshalJSON interface { + MarshalJSON() ([]byte, error) +} + // ExportOption specifies the behavior of function Export. type ExportOption struct { WithoutType bool // WithoutType specifies exported content has no type information. @@ -172,10 +183,31 @@ func doExport(value interface{}, indent string, buffer *bytes.Buffer, option doE RecursiveOption: structs.RecursiveOptionEmbeddedNoTag, }) if len(structFields) == 0 { - if option.WithoutType { - buffer.WriteString("{}") + var ( + structContentStr = "" + attributeCountStr = "0" + ) + if v, ok := value.(iString); ok { + structContentStr = v.String() + } else if v, ok := value.(iMarshalJSON); ok { + b, _ := v.MarshalJSON() + structContentStr = string(b) + } + if structContentStr == "" { + structContentStr = "{}" } else { - buffer.WriteString(fmt.Sprintf("%s(0) {}", reflectTypeName)) + structContentStr = fmt.Sprintf(`"%s"`, gstr.AddSlashes(structContentStr)) + attributeCountStr = fmt.Sprintf(`%d`, len(structContentStr)-2) + } + if option.WithoutType { + buffer.WriteString(structContentStr) + } else { + buffer.WriteString(fmt.Sprintf( + "%s(%s) %s", + reflectTypeName, + attributeCountStr, + structContentStr, + )) } return } diff --git a/util/gutil/gutil_z_unit_dump_test.go b/util/gutil/gutil_z_unit_dump_test.go new file mode 100755 index 000000000..236d07add --- /dev/null +++ b/util/gutil/gutil_z_unit_dump_test.go @@ -0,0 +1,128 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gutil_test + +import ( + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" + "testing" + + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gutil" +) + +func Test_Dump(t *testing.T) { + type CommonReq struct { + AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` + ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` + } + type SetSpecInfo struct { + StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` + Shards int32 `des:"shards 分片数" sum:"Shards Summary"` + Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` + } + type CreateResourceReq struct { + CommonReq + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` + Name string + CreatedAt *gtime.Time + SetMap map[string]*SetSpecInfo + SetSlice []SetSpecInfo + Handler ghttp.HandlerFunc + internal string + } + req := &CreateResourceReq{ + CommonReq: CommonReq{ + AppId: 12345678, + ResourceId: "tdchqy-xxx", + }, + Name: "john", + CreatedAt: gtime.Now(), + SetMap: map[string]*SetSpecInfo{ + "test1": { + StorageType: "ssd", + Shards: 2, + Params: []string{"a", "b", "c"}, + }, + "test2": { + StorageType: "hssd", + Shards: 10, + Params: []string{}, + }, + }, + SetSlice: []SetSpecInfo{ + { + StorageType: "hssd", + Shards: 10, + Params: []string{"h"}, + }, + }, + } + gtest.C(t, func(t *gtest.T) { + gutil.Dump(map[int]int{ + 100: 100, + }) + gutil.Dump(req) + }) +} + +func TestDumpWithType(t *testing.T) { + type CommonReq struct { + AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` + ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` + } + type SetSpecInfo struct { + StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` + Shards int32 `des:"shards 分片数" sum:"Shards Summary"` + Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` + } + type CreateResourceReq struct { + CommonReq + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` + Name string + CreatedAt *gtime.Time + SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` + SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` + Handler ghttp.HandlerFunc + internal string + } + req := &CreateResourceReq{ + CommonReq: CommonReq{ + AppId: 12345678, + ResourceId: "tdchqy-xxx", + }, + Name: "john", + CreatedAt: gtime.Now(), + SetMap: map[string]*SetSpecInfo{ + "test1": { + StorageType: "ssd", + Shards: 2, + Params: []string{"a", "b", "c"}, + }, + "test2": { + StorageType: "hssd", + Shards: 10, + Params: []string{}, + }, + }, + SetSlice: []SetSpecInfo{ + { + StorageType: "hssd", + Shards: 10, + Params: []string{"h"}, + }, + }, + } + gtest.C(t, func(t *gtest.T) { + gutil.DumpWithType(map[int]int{ + 100: 100, + }) + gutil.DumpWithType(req) + gutil.DumpWithType([][]byte{[]byte("hello")}) + }) +} diff --git a/util/gutil/gutil_z_unit_test.go b/util/gutil/gutil_z_unit_test.go index 253b89373..0459ad4f7 100755 --- a/util/gutil/gutil_z_unit_test.go +++ b/util/gutil/gutil_z_unit_test.go @@ -8,129 +8,12 @@ package gutil_test import ( "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/util/gmeta" "testing" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gutil" ) -func Test_Dump(t *testing.T) { - type CommonReq struct { - AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` - ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` - } - type SetSpecInfo struct { - StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` - Shards int32 `des:"shards 分片数" sum:"Shards Summary"` - Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` - } - type CreateResourceReq struct { - CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` - Name string `des:"实例名称"` - Product string `des:"业务类型"` - Region string `v:"required" des:"区域"` - SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` - SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` - Handler ghttp.HandlerFunc - internal string - } - req := &CreateResourceReq{ - CommonReq: CommonReq{ - AppId: 12345678, - ResourceId: "tdchqy-xxx", - }, - Name: "john", - Product: "goframe", - Region: "cd", - SetMap: map[string]*SetSpecInfo{ - "test1": { - StorageType: "ssd", - Shards: 2, - Params: []string{"a", "b", "c"}, - }, - "test2": { - StorageType: "hssd", - Shards: 10, - Params: []string{}, - }, - }, - SetSlice: []SetSpecInfo{ - { - StorageType: "hssd", - Shards: 10, - Params: []string{"h"}, - }, - }, - } - gtest.C(t, func(t *gtest.T) { - gutil.Dump(map[int]int{ - 100: 100, - }) - gutil.Dump(req) - }) -} - -func TestDumpWithType(t *testing.T) { - type CommonReq struct { - AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` - ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` - } - type SetSpecInfo struct { - StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` - Shards int32 `des:"shards 分片数" sum:"Shards Summary"` - Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` - } - type CreateResourceReq struct { - CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` - Name string `des:"实例名称"` - Product string `des:"业务类型"` - Region string `v:"required" des:"区域"` - SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` - SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` - Handler ghttp.HandlerFunc - internal string - } - req := &CreateResourceReq{ - CommonReq: CommonReq{ - AppId: 12345678, - ResourceId: "tdchqy-xxx", - }, - Name: "john", - Product: "goframe", - Region: "cd", - SetMap: map[string]*SetSpecInfo{ - "test1": { - StorageType: "ssd", - Shards: 2, - Params: []string{"a", "b", "c"}, - }, - "test2": { - StorageType: "hssd", - Shards: 10, - Params: []string{}, - }, - }, - SetSlice: []SetSpecInfo{ - { - StorageType: "hssd", - Shards: 10, - Params: []string{"h"}, - }, - }, - } - gtest.C(t, func(t *gtest.T) { - gutil.DumpWithType(map[int]int{ - 100: 100, - }) - gutil.DumpWithType(req) - gutil.DumpWithType([][]byte{[]byte("hello")}) - }) -} - func Test_Try(t *testing.T) { gtest.C(t, func(t *gtest.T) { s := `gutil Try test`