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

如何在C#中对含字符串与对象的动态列表进行(De)Serialize并转为自定义对象?

在C#中处理混合类型列表的(De)Serialize

当然可以在C#中处理这种混合了字符串和对象的动态列表的序列化/反序列化!这种异构类型的JSON结构确实需要特殊处理,下面我会给出几种实用的实现方案,分别基于Newtonsoft.Json(Json.NET)和内置的System.Text.Json。

首先,我们先定义核心的Permission类,用来映射JSON中的对象结构:

public class Permission
{
    public string PermissionName { get; set; }
    public string Namespace { get; set; }
}

方案一:直接反序列化为混合类型列表再处理

如果只是临时处理这种混合结构,可以先把列表反序列化为List<object>或者dynamic,然后逐个判断元素类型并转换为Permission对象。这里以Newtonsoft.Json为例:

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

class Program
{
    static void Main()
    {
        // 你的示例JSON
        string json = @"
        {
            ""permission"": [ ""Group1"", ""Group2"", { ""PermissionName"" : ""QA"", ""Namespace"" : ""Namespace1"" } ]
        }";

        // 先反序列化为动态对象
        var dynamicResult = JsonConvert.DeserializeObject<dynamic>(json);
        List<object> rawPermissions = dynamicResult.permission.ToObject<List<object>>();

        // 转换为统一的Permission列表
        List<Permission> permissions = new List<Permission>();
        foreach (var item in rawPermissions)
        {
            if (item is string groupName)
            {
                // 字符串类型直接转为Permission,Namespace设为null/空
                permissions.Add(new Permission { PermissionName = groupName });
            }
            else if (item is JObject jObj)
            {
                // JObject类型直接反序列化为Permission
                permissions.Add(jObj.ToObject<Permission>());
            }
        }

        // 输出结果验证
        foreach (var p in permissions)
        {
            Console.WriteLine($"权限名称: {p.PermissionName}, 命名空间: {p.Namespace ?? "无"}");
        }
    }
}

方案二:自定义Json转换器(推荐)

如果需要长期处理这种结构,自定义Json转换器是更优雅的方式——它能自动完成字符串和对象之间的转换,让你直接反序列化为List<Permission>,序列化时也能保持原JSON的混合格式。

基于Newtonsoft.Json的转换器

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

public class PermissionConverter : JsonConverter<Permission>
{
    public override Permission ReadJson(JsonReader reader, Type objectType, Permission existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 处理字符串类型的元素
        if (reader.TokenType == JsonToken.String)
        {
            return new Permission { PermissionName = (string)reader.Value };
        }
        // 处理对象类型的元素
        else if (reader.TokenType == JsonToken.StartObject)
        {
            JObject jObj = JObject.Load(reader);
            return jObj.ToObject<Permission>();
        }
        throw new JsonException("无法识别的权限类型");
    }

    public override void WriteJson(JsonWriter writer, Permission value, JsonSerializer serializer)
    {
        // 序列化时,如果Namespace为空,输出字符串;否则输出对象
        if (string.IsNullOrEmpty(value.Namespace))
        {
            writer.WriteValue(value.PermissionName);
        }
        else
        {
            serializer.Serialize(writer, value);
        }
    }
}

// 定义根对象类来匹配JSON结构
public class RootObject
{
    [JsonProperty("permission")]
    public List<Permission> Permission { get; set; }
}

class Program
{
    static void Main()
    {
        string json = @"
        {
            ""permission"": [ ""Group1"", ""Group2"", { ""PermissionName"" : ""QA"", ""Namespace"" : ""Namespace1"" } ]
        }";

        // 配置序列化设置,添加自定义转换器
        var settings = new JsonSerializerSettings();
        settings.Converters.Add(new PermissionConverter());

        // 直接反序列化为RootObject
        var result = JsonConvert.DeserializeObject<RootObject>(json, settings);

        // 验证反序列化结果
        foreach (var p in result.Permission)
        {
            Console.WriteLine($"权限名称: {p.PermissionName}, 命名空间: {p.Namespace ?? "无"}");
        }

        // 序列化回去,验证格式是否和原JSON一致
        string serializedJson = JsonConvert.SerializeObject(result, Formatting.Indented, settings);
        Console.WriteLine("\n序列化后的JSON:");
        Console.WriteLine(serializedJson);
    }
}

基于System.Text.Json的转换器

如果你用的是.NET Core 3.0+或.NET 5+,可以直接用内置的System.Text.Json实现:

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

public class PermissionConverter : JsonConverter<Permission>
{
    public override Permission Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.String)
        {
            return new Permission { PermissionName = reader.GetString() };
        }
        else if (reader.TokenType == JsonTokenType.StartObject)
        {
            return JsonSerializer.Deserialize<Permission>(ref reader, options);
        }
        throw new JsonException("无法识别的权限类型");
    }

    public override void Write(Utf8JsonWriter writer, Permission value, JsonSerializerOptions options)
    {
        if (string.IsNullOrEmpty(value.Namespace))
        {
            writer.WriteStringValue(value.PermissionName);
        }
        else
        {
            JsonSerializer.Serialize(writer, value, options);
        }
    }
}

public class RootObject
{
    [JsonPropertyName("permission")]
    public List<Permission> Permission { get; set; }
}

class Program
{
    static void Main()
    {
        string json = @"
        {
            ""permission"": [ ""Group1"", ""Group2"", { ""PermissionName"" : ""QA"", ""Namespace"" : ""Namespace1"" } ]
        }";

        var options = new JsonSerializerOptions();
        options.Converters.Add(new PermissionConverter());
        options.WriteIndented = true;

        var result = JsonSerializer.Deserialize<RootObject>(json, options);

        foreach (var p in result.Permission)
        {
            Console.WriteLine($"权限名称: {p.PermissionName}, 命名空间: {p.Namespace ?? "无"}");
        }

        string serializedJson = JsonSerializer.Serialize(result, options);
        Console.WriteLine("\n序列化后的JSON:");
        Console.WriteLine(serializedJson);
    }
}

总结

  • 临时处理用方案一,快速灵活;
  • 长期维护用方案二,代码更整洁,序列化/反序列化逻辑统一;
  • 两种主流的JSON库都支持自定义转换器,根据你的项目环境选择即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:37:46