From f9024b9498347bffba70505cd6b20525230c4255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 28 Apr 2025 17:34:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=8Ejson=20->=20xml?= =?UTF-8?q?=E7=9A=84=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- builder.go | 3 +- go.mod | 2 +- go.sum | 2 + wrapper/json.go | 136 +++++++++++++++++++++++++++++++++++++++++++ wrapper/json_test.go | 22 +++++++ 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 wrapper/json.go create mode 100644 wrapper/json_test.go diff --git a/builder.go b/builder.go index 8ca20a4..ad64070 100644 --- a/builder.go +++ b/builder.go @@ -67,8 +67,9 @@ func (b *builderImpl) AddField(name string, pkg string, typ any, tag string, ano tag = cfgTag } else { if len(tag) == 0 { + arr := strings.Split(strings.TrimSuffix(name, ".[]"), ".") // 没指定tag, 字段名称作为tag名称 - tag = strings.ReplaceAll(`json:"{TAG_NAME}" xml:"{TAG_NAME}" toml:"{TAG_NAME}" yaml:"{TAG_NAME}" ini:"{TAG_NAME}"`, "{TAG_NAME}", name) + tag = strings.ReplaceAll(`json:"{TAG_NAME}" xml:"{TAG_NAME}" toml:"{TAG_NAME}" yaml:"{TAG_NAME}" ini:"{TAG_NAME}"`, "{TAG_NAME}", arr[len(arr)-1]) // tag = fmt.Sprintf(`json:"%s"`, name) } } diff --git a/go.mod b/go.mod index 8504734..e685e2f 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( require ( git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995 // indirect git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect - git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250426132259-73cf1be49c7f // indirect + git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250428041157-135850ee8a58 // indirect git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect github.com/BurntSushi/toml v1.5.0 // indirect github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect diff --git a/go.sum b/go.sum index 201c497..2b84ee9 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7G git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250426132259-73cf1be49c7f h1:7QgAcGnmVEVyIPeWH0ZkQN/jpzklYXsKCenTR2GpxbE= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250426132259-73cf1be49c7f/go.mod h1:Ig3GZC2hJDkQp7F8Tm53GvMWLh9bdbbauow/vxGO4YA= +git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250428041157-135850ee8a58 h1:fTkmucGaUoKocoX+ASM4AnwsAVJOtOOLUFSqA+uwVzg= +git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250428041157-135850ee8a58/go.mod h1:Ig3GZC2hJDkQp7F8Tm53GvMWLh9bdbbauow/vxGO4YA= git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI= git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI= git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250302133417-c1588abcb436 h1:SM4zc54W2wmM72+4pMNQ8iS371H6lj4J8rj8KJKf7pw= diff --git a/wrapper/json.go b/wrapper/json.go new file mode 100644 index 0000000..0a6dd8f --- /dev/null +++ b/wrapper/json.go @@ -0,0 +1,136 @@ +// Package wrapper ... +// +// Description : wrapper ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2025-04-28 15:32 +package wrapper + +import ( + "encoding/xml" + "errors" + dynamicstruct "git.zhangdeman.cn/zhangdeman/dynamic-struct" + "git.zhangdeman.cn/zhangdeman/serialize" + "github.com/tidwall/gjson" +) + +func NewJson(sourceData string) (*ownJson, error) { + gjsonRes := gjson.Parse(sourceData) + if gjsonRes.Value() == nil { + return nil, errors.New("source data parse result is nil") + } + // 仅支持map + if !gjsonRes.IsObject() { + return nil, errors.New("source result is not map or struct Marshal string") + } + oj := &ownJson{ + sourceData: sourceData, + gjsonResult: gjsonRes, + structBuilder: dynamicstruct.NewStruct(nil), + } + if err := oj.GenerateStruct(); nil != err { + return nil, err + } + return oj, nil +} + +type ownJson struct { + sourceData string // 数据源 + gjsonResult gjson.Result // 数据源解析为gjson + structBuilder dynamicstruct.IBuilder // 结构体构造器 + structRes any // 解析的结构体值 +} + +// GenerateStruct 生成结构体字段列表 +func (oj *ownJson) GenerateStruct() error { + oj.gjsonResult.ForEach(func(fieldName, fieldValue gjson.Result) bool { + oj.generateStructField("", fieldName.String(), fieldValue) + return true + }) + // 追加xml的标签 + oj.structBuilder.AddField("XMLName", "", xml.Name{}, `json:"-" xml:"XmlData"`, false) + val := oj.structBuilder.Build().New() + if err := serialize.JSON.UnmarshalWithNumber([]byte(oj.sourceData), &val); nil != err { + return err + } + oj.structRes = val + return nil +} + +// Marshal 结果序列化 +func (oj *ownJson) Marshal(marshalType string) ([]byte, error) { + return serialize.Wrapper.Marshal(marshalType, oj.structRes) +} + +// generateStructField 递归解析 +func (oj *ownJson) generateStructField(rootPath string, currentName string, currentResult gjson.Result) { + structPath := oj.getPath(rootPath, currentName) + if currentResult.IsBool() { + // bool类型 + oj.structBuilder.AddField(structPath, "", true, "", false) + return + } + if currentResult.Type == gjson.Number { + // 数字类型, 统一用float64 + oj.structBuilder.AddField(structPath, "", float64(0), "", false) + return + } + if currentResult.Value() == nil { + // 空值, any类型 + oj.structBuilder.AddField(structPath, "", (*any)(nil), "", false) + return + } + if currentResult.Type == gjson.String { + // 字符串类型 + oj.structBuilder.AddField(structPath, "", "", "", false) + return + } + if currentResult.IsObject() { + // 还是一个嵌套对象, 递归处理 + currentResult.ForEach(func(key, value gjson.Result) bool { + oj.generateStructField(structPath, key.String(), value) + return true + }) + return + } + if currentResult.IsArray() { + // 数组, 递归处理 + arrList := currentResult.Array() + if arrList[0].Type == gjson.True || arrList[0].Type == gjson.False { + oj.structBuilder.AddField(structPath, "", []bool{}, "", false) + return + } + if arrList[0].Type == gjson.Number { + oj.structBuilder.AddField(structPath, "", []float64{}, "", false) + return + } + if arrList[0].Type == gjson.String { + oj.structBuilder.AddField(structPath, "", []string{}, "", false) + return + } + if arrList[0].Type == gjson.Null { + oj.structBuilder.AddField(structPath, "", []any{}, "", false) + return + } + if arrList[0].IsArray() { + // 数组就不递归处理了, 支持到二维 + oj.structBuilder.AddField(structPath, "", [][]any{}, "", false) + return + } + // 对象结构,递归处理 + arrList[0].ForEach(func(key, value gjson.Result) bool { + oj.generateStructField(structPath+".[]", key.String(), value) + return true + }) + return + } +} + +// getPath 获取路径 +func (oj *ownJson) getPath(root string, currentName string) string { + if root == "" { + return currentName + } + return root + "." + currentName +} diff --git a/wrapper/json_test.go b/wrapper/json_test.go new file mode 100644 index 0000000..6d676bf --- /dev/null +++ b/wrapper/json_test.go @@ -0,0 +1,22 @@ +// Package wrapper ... +// +// Description : wrapper ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2025-04-28 16:59 +package wrapper + +import ( + "fmt" + "testing" +) + +func TestNewJson(t *testing.T) { + sourceData := `{"name": "test", "age":18,"company":{"address": "Beijing", "name":"lala"},"index":[1,2,3,4], "deep":[{"name":"a"}]}` + instance, iErr := NewJson(sourceData) + fmt.Println(iErr) + res, err := instance.Marshal("xml") + fmt.Println(err) + fmt.Println(string(res)) +}