You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现XML到JSON动态映射,解决自定义对象数组递归映射问题

嵌套对象数组的XML到JSON动态递归映射解决方案(C#)

针对你对接Actionstep API时遇到的自定义对象数组递归映射问题,以下是可落地的实现方案:

一、扩展数据库映射规则表

首先需要调整映射规则的存储结构,让它能描述嵌套对象的层级关系:

  • 新增ParentMappingId字段:关联父级对象的映射ID,标记当前字段属于哪个嵌套对象
  • 新增IsArray字段:标记当前是否为数组类型,结合FieldType区分是原始数组还是自定义对象数组

示例规则(针对friends数组):

IDSourceXPathTargetJsonPathFieldTypeParentMappingIdIsArray
1/root/friends$.friendsObjectNULL1
2/root/friends/*/name$.friends[*].nameString10
3/root/friends/*/age$.friends[*].ageInt10

二、递归映射核心逻辑实现

通过递归方法处理嵌套对象数组,核心流程是:识别数组规则→遍历XML子节点→创建对应JSON对象→递归填充子字段→组装数组并赋值到目标路径。

代码示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Newtonsoft.Json.Linq;

public class XmlToJsonDynamicMapper
{
    // 映射规则模型(与数据库表结构对应)
    public class MappingRule
    {
        public int Id { get; set; }
        public string SourceXPath { get; set; }
        public string TargetJsonPath { get; set; }
        public string FieldType { get; set; }
        public int? ParentMappingId { get; set; }
        public bool IsArray { get; set; }
    }

    private readonly List<MappingRule> _mappingRules;

    public XmlToJsonDynamicMapper(List<MappingRule> rules)
    {
        _mappingRules = rules;
    }

    public JObject Map(XmlDocument inputXml, JObject actionstepJsonTemplate)
    {
        // 先处理顶级无父级的映射规则
        var topLevelRules = _mappingRules.Where(r => !r.ParentMappingId.HasValue).ToList();
        ProcessNodeMapping(inputXml.DocumentElement, actionstepJsonTemplate, topLevelRules);
        return actionstepJsonTemplate;
    }

    private void ProcessNodeMapping(XmlNode currentXmlNode, JToken currentJsonNode, List<MappingRule> rules)
    {
        foreach (var rule in rules)
        {
            if (rule.IsArray)
            {
                // 处理自定义对象数组
                var xmlArrayNodes = currentXmlNode.SelectNodes(rule.SourceXPath);
                if (xmlArrayNodes == null || xmlArrayNodes.Count == 0) continue;

                var childRules = _mappingRules.Where(r => r.ParentMappingId == rule.Id).ToList();
                var jsonArray = new JArray();

                foreach (XmlNode itemXmlNode in xmlArrayNodes)
                {
                    var itemJsonObject = new JObject();
                    // 递归处理数组内每个对象的字段映射
                    ProcessNodeMapping(itemXmlNode, itemJsonObject, childRules);
                    jsonArray.Add(itemJsonObject);
                }

                // 将组装好的数组赋值到JSON模板对应路径
                SetJsonValue(currentJsonNode, rule.TargetJsonPath, jsonArray);
            }
            else
            {
                // 处理基础类型字段
                var xmlValue = currentXmlNode.SelectSingleNode(rule.SourceXPath)?.InnerText;
                if (string.IsNullOrWhiteSpace(xmlValue)) continue;

                var jsonValue = ConvertToJToken(xmlValue, rule.FieldType);
                SetJsonValue(currentJsonNode, rule.TargetJsonPath, jsonValue);
            }
        }
    }

    // 类型转换:将XML文本值转为对应JSON类型
    private JToken ConvertToJToken(string value, string fieldType)
    {
        return fieldType switch
        {
            "Int" => JToken.Parse(value),
            "Boolean" => JToken.Parse(value.ToLower()),
            "DateTime" => JToken.Parse(DateTime.Parse(value).ToString("yyyy-MM-ddTHH:mm:ssZ")),
            "Decimal" => JToken.Parse(value),
            _ => JToken.FromObject(value) // 默认转为字符串
        };
    }

    // 按JSON路径赋值,支持数组路径标识
    private void SetJsonValue(JToken rootNode, string jsonPath, JToken value)
    {
        var pathSegments = jsonPath.Replace("$.", "").Split('.');
        var currentNode = rootNode;

        for (int i = 0; i < pathSegments.Length; i++)
        {
            var segment = pathSegments[i];
            if (segment.EndsWith("[*]"))
            {
                // 数组节点直接赋值
                segment = segment.Replace("[*]", "");
                currentNode[segment] = value;
                break;
            }

            if (i == pathSegments.Length - 1)
            {
                currentNode[segment] = value;
            }
            else
            {
                // 不存在则创建嵌套对象
                currentNode[segment] ??= new JObject();
                currentNode = currentNode[segment];
            }
        }
    }
}

三、对接Actionstep API的整合流程

  1. 获取JSON模板:通过GET请求调用Actionstep API的创建Action接口,获取模板JSON
  2. 加载映射规则:从数据库读取包含嵌套数组规则的完整映射列表
  3. 解析输入XML:将外部传入的XML数据解析为XmlDocument对象
  4. 执行映射:实例化XmlToJsonDynamicMapper,调用Map方法填充JSON模板
  5. 提交数据:将填充完成的JSON通过POST请求提交到Actionstep API

四、关键注意事项

  • XPath路径要精准:数组子项需用/*匹配所有子节点(如/root/friends/*/name)
  • JSON路径兼容:支持$.friends[*].name这种数组元素的路径写法
  • 空值容错:XML节点不存在时跳过赋值,避免覆盖JSON模板的默认配置
  • 类型校验:严格按FieldType做类型转换,防止JSON格式不符合API要求

内容的提问来源于stack exchange,提问作者Hardipsinh Jadeja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:08:29