137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
// 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
|
|
}
|