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
}