You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C#中反序列化JSON数组(或列表)?代码实现疑问

正确反序列化嵌套复杂JSON数组为C#列表的方案

首先得指出你原来代码里的几个问题:

  1. JSON字符串的变量声明语法错误(缺少string类型);
  2. 直接尝试把整个JSON反序列化成List<Cookie>是行不通的——你的JSON结构嵌套非常深,最外层是包含head的对象,Rows数组里混合了字符串和多层嵌套数组,完全和List<Cookie>的结构不匹配。

下面给你两种可行的实现方案,分别用目前最常用的两个JSON序列化库:


方案一:使用Newtonsoft.Json(Json.NET,推荐)

这个库对复杂JSON结构的支持更友好,处理动态类型和嵌套数组更方便。

步骤1:定义匹配JSON结构的实体类

// 最外层根对象
public class Root
{
    public Head head { get; set; }
}

// Head对象,包含Rows数组(混合类型,所以用object[])
public class Head
{
    public object[] Rows { get; set; }
}

// 匹配JSON里的键值对对象
public class CookieItem
{
    [JsonProperty("@Key")] // 映射JSON里的@Key字段
    public string Key { get; set; }

    [JsonProperty("@value")] // 映射JSON里的@value字段
    public string Value { get; set; }
}

// 你最终需要的Cookie实体
public class Cookie
{
    public string Domain { get; set; }
    public string CookieName { get; set; }
    public string Purpose { get; set; }
    public string Lifetime { get; set; }
}

步骤2:实现反序列化逻辑

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static List<Cookie> DeserializeNames()
{
    // 修正后的JSON字符串(补全变量类型声明)
    string jsonStream = "{ \"head\": { \"Rows\": [ \"test 1\", [ [ { \"@Key\": \"Domain\", \"@value\": \"LocalHost\" }, { \"@Key\": \"Cookie name(s)\", \"@value\": \"Google\" }, { \"@Key\": \"Purpose\", \"@value\": \"Test\" }, { \"@Key\": \"lifetime\", \"@value\": \"test\" } ] ] ] } }";

    // 1. 先反序列化为根对象
    var root = JsonConvert.DeserializeObject<Root>(jsonStream);

    // 2. 逐层提取嵌套的键值对数组
    // Rows[1]是嵌套的数组,里面的[0]又是一层数组,包含我们需要的Cookie键值对
    var cookieItems = ((JArray)((JArray)root.head.Rows[1])[0]).ToObject<List<CookieItem>>();

    // 3. 将键值对转换为Cookie对象
    var cookie = new Cookie();
    foreach (var item in cookieItems)
    {
        switch (item.Key)
        {
            case "Domain":
                cookie.Domain = item.Value;
                break;
            case "Cookie name(s)":
                cookie.CookieName = item.Value;
                break;
            case "Purpose":
                cookie.Purpose = item.Value;
                break;
            case "lifetime":
                cookie.Lifetime = item.Value;
                break;
        }
    }

    // 如果后续有多个Cookie组,这里可以扩展逻辑,当前返回包含单个Cookie的列表
    return new List<Cookie> { cookie };
}

方案二:使用.NET Framework原生的JavaScriptSerializer

如果你只能用原生的JavaScriptSerializer,可以这样实现(注意:这个库对复杂类型的支持有限,代码会更繁琐):

步骤1:定义实体类

using System.Web.Script.Serialization;

// 最外层根对象
public class Root
{
    public Head head { get; set; }
}

public class Head
{
    public object[] Rows { get; set; }
}

// 因为JavaScriptSerializer会直接匹配属性名,所以用@转义C#的关键字/特殊命名
public class CookieItem
{
    public string @Key { get; set; }
    public string @value { get; set; }
}

// 目标Cookie实体和方案一一致
public class Cookie
{
    public string Domain { get; set; }
    public string CookieName { get; set; }
    public string Purpose { get; set; }
    public string Lifetime { get; set; }
}

步骤2:实现反序列化逻辑

public static List<Cookie> DeserializeNames()
{
    string jsonStream = "{ \"head\": { \"Rows\": [ \"test 1\", [ [ { \"@Key\": \"Domain\", \"@value\": \"LocalHost\" }, { \"@Key\": \"Cookie name(s)\", \"@value\": \"Google\" }, { \"@Key\": \"Purpose\", \"@value\": \"Test\" }, { \"@Key\": \"lifetime\", \"@value\": \"test\" } ] ] ] } }";

    JavaScriptSerializer serializer = new JavaScriptSerializer();
    // 先反序列化为动态对象
    dynamic root = serializer.DeserializeObject(jsonStream);

    // 逐层访问嵌套数组
    var rows = root["head"]["Rows"] as System.Collections.ArrayList;
    var innerArray = rows[1] as System.Collections.ArrayList;
    var cookieItemsArray = innerArray[0] as System.Collections.ArrayList;

    // 将数组转换为CookieItem列表
    List<CookieItem> cookieItems = serializer.ConvertToType<List<CookieItem>>(cookieItemsArray);

    // 转换为目标Cookie对象
    Cookie cookie = new Cookie();
    foreach (var item in cookieItems)
    {
        switch (item.@Key)
        {
            case "Domain":
                cookie.Domain = item.@value;
                break;
            case "Cookie name(s)":
                cookie.CookieName = item.@value;
                break;
            case "Purpose":
                cookie.Purpose = item.@value;
                break;
            case "lifetime":
                cookie.Lifetime = item.@value;
                break;
        }
    }

    return new List<Cookie> { cookie };
}

关键说明

  • 永远要让C#实体类的结构匹配JSON的层级,不能跳过嵌套直接反序列化为目标类型;
  • 如果JSON里有混合类型的数组(比如同时包含字符串和数组),要用object[]或者动态类型来承接;
  • 优先选择Newtonsoft.Json,它的功能更强大,处理复杂JSON的效率和灵活性都远高于原生的JavaScriptSerializer

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

火山引擎 最新活动