246 lines
6.3 KiB
Go
246 lines
6.3 KiB
Go
package pkg
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"gitea.cdlsxd.cn/self-tools/tysk/tysk_constant"
|
||
"github.com/clbanning/mxj"
|
||
"reflect"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
// XmlRequest 定义请求结构
|
||
type XmlRequest struct {
|
||
Action tysk_constant.RequestCode `xml:"action"`
|
||
UserName string `xml:"userName"`
|
||
ExtraFields map[string]interface{} `xml:"-"` // 忽略此字段,手动处理
|
||
}
|
||
|
||
// MarshalToXML 将XmlRequest转换为指定格式的XML字节流
|
||
func (req XmlRequest) MarshalToXML() ([]byte, error) {
|
||
var buf bytes.Buffer
|
||
|
||
// 写入XML声明
|
||
buf.WriteString(`<?xml version="1.0" encoding="GBK"?>` + "\n")
|
||
buf.WriteString("<stream>\n")
|
||
|
||
// 写入基本字段
|
||
buf.WriteString(fmt.Sprintf("<action>%s</action>\n", req.Action))
|
||
buf.WriteString(fmt.Sprintf("<userName>%s</userName>\n", req.UserName))
|
||
|
||
// 处理ExtraFields
|
||
for key, value := range req.ExtraFields {
|
||
switch v := value.(type) {
|
||
case []map[string]interface{}:
|
||
// 处理列表数据
|
||
buf.WriteString(fmt.Sprintf("<list name=\"%s\">\n", key))
|
||
for _, row := range v {
|
||
if len(row) == 0 {
|
||
continue
|
||
}
|
||
buf.WriteString("<row>\n")
|
||
for rowKey, rowValue := range row {
|
||
buf.WriteString(fmt.Sprintf("<%s>%s</%s>\n", rowKey, ToString(rowValue), rowKey))
|
||
}
|
||
buf.WriteString("</row>\n")
|
||
}
|
||
buf.WriteString("</list>\n")
|
||
// 可以根据需要添加其他类型的处理
|
||
case []string:
|
||
// 处理列表数据
|
||
buf.WriteString(fmt.Sprintf("<list name=\"%s\">\n", key))
|
||
buf.WriteString("<row>\n")
|
||
for _, row := range v {
|
||
buf.WriteString(fmt.Sprintf("<%s>%s</%s>\n", key, row, key))
|
||
}
|
||
buf.WriteString("</row>\n")
|
||
buf.WriteString("</list>\n")
|
||
// 可以根据需要添加其他类型的处理
|
||
case map[string]interface{}:
|
||
// 处理列表数据
|
||
buf.WriteString(fmt.Sprintf("<list name=\"%s\">\n", key))
|
||
|
||
for rowKey, row := range v {
|
||
switch row.(type) {
|
||
case []interface{}:
|
||
for _, rowValue := range row.([]interface{}) {
|
||
buf.WriteString("<row>\n")
|
||
buf.WriteString(fmt.Sprintf("<%s>%s</%s>\n", rowKey, rowValue, rowKey))
|
||
buf.WriteString("</row>\n")
|
||
}
|
||
default:
|
||
buf.WriteString("<row>\n")
|
||
buf.WriteString(fmt.Sprintf("<%s>%s</%s>\n", key, row, key))
|
||
buf.WriteString("</row>\n")
|
||
}
|
||
}
|
||
|
||
buf.WriteString("</list>\n")
|
||
// 可以根据需要添加其他类型的处理
|
||
default:
|
||
buf.WriteString(fmt.Sprintf("<%s>%s</%s>\n", key, ToString(v), key))
|
||
}
|
||
}
|
||
|
||
buf.WriteString("</stream>")
|
||
return buf.Bytes(), nil
|
||
}
|
||
|
||
func XMLToByte(xmlBytes []byte) ([]byte, error) {
|
||
// 去掉XML声明
|
||
if idx := bytes.Index(xmlBytes, []byte("?>")); idx != -1 {
|
||
xmlBytes = xmlBytes[idx+2:]
|
||
}
|
||
// 解析XML
|
||
mv, err := mxj.NewMapXml(xmlBytes)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("XML 解析失败: %v", err)
|
||
}
|
||
// 获取stream节点
|
||
stream, ok := mv["stream"].(map[string]interface{})
|
||
if !ok {
|
||
return nil, fmt.Errorf("无效的XML结构: 缺少stream节点")
|
||
}
|
||
// 处理list节点
|
||
if lists, ok := stream["list"]; ok {
|
||
switch lists.(type) {
|
||
case []interface{}:
|
||
for _, listItem := range lists.([]interface{}) {
|
||
if listMap, ok := listItem.(map[string]interface{}); ok {
|
||
// 获取name属性
|
||
if name, ok := listMap["-name"].(string); ok && name != "" {
|
||
// 用name作为key,替换原来的list数组
|
||
if rowList, ok := listMap["row"].(map[string]interface{}); ok {
|
||
stream[name] = []map[string]interface{}{rowList}
|
||
} else {
|
||
stream[name] = listMap["row"]
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
case map[string]interface{}:
|
||
listMap := lists.(map[string]interface{})
|
||
if name, ok := listMap["-name"].(string); ok && name != "" {
|
||
// 用name作为key,替换原来的list数组
|
||
if rowList, ok := listMap["row"].(map[string]interface{}); ok {
|
||
stream[name] = []map[string]interface{}{rowList}
|
||
} else {
|
||
stream[name] = listMap["row"]
|
||
}
|
||
|
||
}
|
||
|
||
default:
|
||
}
|
||
|
||
// 删除原始的list节点
|
||
delete(stream, "list")
|
||
}
|
||
// 转换为JSON
|
||
jsonData, err := json.Marshal(stream)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
|
||
return jsonData, nil
|
||
}
|
||
|
||
func SliceToMap(list []interface{}) (listMap []map[string]interface{}) {
|
||
listMap = make([]map[string]interface{}, len(list))
|
||
//for _, accountNo := range list {
|
||
// listMap = append(list, map[string]interface{}{"accountNo": accountNo})
|
||
//}
|
||
return
|
||
}
|
||
|
||
func IsStruct(v interface{}) bool {
|
||
if v == nil {
|
||
return false
|
||
}
|
||
t := reflect.TypeOf(v)
|
||
if t.Kind() == reflect.Ptr {
|
||
t = t.Elem()
|
||
}
|
||
return t.Kind() == reflect.Struct
|
||
}
|
||
|
||
// StructToMap 将一个struct转换为map[string]interface{}
|
||
func StructToMap(obj interface{}) map[string]interface{} {
|
||
// 获取obj的类型
|
||
val := reflect.ValueOf(obj)
|
||
if val.Kind() == reflect.Ptr {
|
||
val = val.Elem()
|
||
}
|
||
|
||
// 确保obj是一个struct
|
||
if val.Kind() != reflect.Struct {
|
||
return nil
|
||
}
|
||
|
||
// 创建一个map来保存结果
|
||
data := make(map[string]interface{})
|
||
|
||
// 遍历struct的字段
|
||
for i := 0; i < val.NumField(); i++ {
|
||
// 获取字段的类型和值
|
||
valueField := val.Field(i)
|
||
typeField := val.Type().Field(i)
|
||
jsonTag := typeField.Tag.Get("json")
|
||
if idx := strings.Index(jsonTag, ","); idx != -1 {
|
||
// 如果有逗号,则取逗号之前的部分
|
||
jsonTag = jsonTag[:idx]
|
||
}
|
||
// 忽略未导出的字段(字段名首字母小写)
|
||
if !typeField.IsExported() {
|
||
continue
|
||
}
|
||
|
||
// 将字段名和值添加到map中
|
||
data[jsonTag] = valueField.Interface()
|
||
}
|
||
|
||
return data
|
||
}
|
||
|
||
func ToString(v interface{}) string {
|
||
switch v := v.(type) {
|
||
case int:
|
||
return strconv.Itoa(v)
|
||
case float64:
|
||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||
case bool:
|
||
return strconv.FormatBool(v)
|
||
case string:
|
||
return v
|
||
case fmt.Stringer: // 实现了 String() 接口的类型
|
||
return v.String()
|
||
default:
|
||
return fmt.Sprintf("%v", v) // 其他类型 fallback
|
||
}
|
||
}
|
||
|
||
// BuildNestedMap 通用方法:根据动态路径(如 "userDataList.rcptNum")构造嵌套 map
|
||
func BuildNestedMap(path string, value interface{}) (map[string]interface{}, string) {
|
||
keys := strings.Split(path, ".")
|
||
result := make(map[string]interface{})
|
||
current := result
|
||
|
||
// 迭代处理每一级 key
|
||
for i, key := range keys {
|
||
if i == len(keys)-1 {
|
||
// 最后一层,赋值
|
||
current[key] = value
|
||
} else {
|
||
// 非最后一层,创建嵌套 map
|
||
newMap := make(map[string]interface{})
|
||
current[key] = newMap
|
||
current = newMap
|
||
}
|
||
}
|
||
|
||
return result, keys[0]
|
||
}
|