tysk/pkg/func.go

260 lines
6.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 []interface{}:
// 处理列表数据
buf.WriteString(fmt.Sprintf("<list name=\"%s\">\n", key))
for _, row := range v {
buf.WriteString("<row>\n")
if vmap, isMapList := row.(map[string]interface{}); isMapList {
for rowKey, rowValue := range vmap {
buf.WriteString(fmt.Sprintf("<%s>%v</%s>\n", rowKey, rowValue, rowKey))
}
}
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]
}