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

C#中如何将嵌套JSON数组反序列化为ExpandoObject的数组?

解决Json.NET反序列化ExpandoObject时嵌套数组转为List导致Jint无法调用数组方法的问题

问题场景

  • 无预定义强类型类,需反序列化带嵌套数组的JSON对象
  • 使用ExpandoObjectConverter反序列化为ExpandoObject时,嵌套数组会被转为List<T>,Jint引擎无法识别该类型,调用filter/map等JS数组方法失败
  • 使用JObject解析时,JArray同样不支持JS数组原生方法
  • 仅定义强类型类并将嵌套结构声明为数组时,Jint才能正常执行预期逻辑

解决方案

核心思路是让Json.NET在反序列化嵌套数组时直接生成CLR数组而非List<T>,提供两种可行实现:

方案1:自定义ExpandoObjectConverter

继承默认的ExpandoObjectConverter,重写ReadJson方法,遇到数组时将元素转成数组返回:

using System.Collections.Generic;
using System.Dynamic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class ExpandoWithArraysConverter : ExpandoObjectConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 处理数组节点:递归反序列化每个元素后转为数组
        if (reader.TokenType == JsonToken.StartArray)
        {
            var elements = new List<object>();
            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
            {
                elements.Add(base.ReadJson(reader, typeof(ExpandoObject), null, serializer));
            }
            return elements.ToArray();
        }
        // 其他节点沿用默认逻辑
        return base.ReadJson(reader, objectType, existingValue, serializer);
    }
}

使用方式:

dynamic v = JsonConvert.DeserializeObject<ExpandoObject>(obj, new ExpandoWithArraysConverter());

方案2:JToken转动态对象(手动递归转换)

先将JSON解析为JObject,再递归遍历所有节点,把JArray转为CLR数组、JObject转为ExpandoObject:

using System.Dynamic;
using Newtonsoft.Json.Linq;

public static object ConvertJTokenToDynamic(JToken token)
{
    return token.Type switch
    {
        JTokenType.Object => ConvertJObjectToExpando(token as JObject),
        JTokenType.Array => token.Select(ConvertJTokenToDynamic).ToArray(),
        _ => ((JValue)token).Value
    };
}

private static ExpandoObject ConvertJObjectToExpando(JObject jObj)
{
    var expando = new ExpandoObject();
    var dict = (IDictionary<string, object>)expando;
    foreach (var prop in jObj.Properties())
    {
        dict[prop.Name] = ConvertJTokenToDynamic(prop.Value);
    }
    return expando;
}

使用方式:

var jObj = JObject.Parse(obj);
dynamic v = ConvertJTokenToDynamic(jObj);

验证效果

使用原示例代码测试,两种方案都能让Jint正常执行eval函数,返回预期结果30(13+17)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:00:58