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

C#对象序列化如何实现动态属性名?求最佳反序列化方案

实现动态属性名的序列化与反序列化方案

当然可以实现你想要的序列化需求!下面我会基于C#生态里最常用的两个JSON处理库(Newtonsoft.Json/Json.NET和System.Text.Json),分别讲解序列化的实现方式,以及最佳的反序列化方案。

一、序列化实现

1. 快速实现:匿名对象/字典映射

如果只是简单场景,不需要复用逻辑,直接用匿名对象或者字典来转换是最快捷的:

Newtonsoft.Json 版本

var home = new Home { Id = 2, propertyName = "administration", Text = "text1" };
var json = JsonConvert.SerializeObject(new {
    home.Id,
    [home.propertyName] = home.Text
});

System.Text.Json 版本

var home = new Home { Id = 2, propertyName = "administration", Text = "text1" };
var jsonDict = new Dictionary<string, object>
{
    { "Id", home.Id },
    { home.propertyName, home.Text }
};
var json = JsonSerializer.Serialize(jsonDict);

2. 通用方案:自定义Json转换器

如果需要在多个场景复用这个序列化逻辑,或者处理更复杂的对象结构,自定义Json转换器是更优雅的选择:

Newtonsoft.Json 自定义转换器

public class HomeConverter : JsonConverter<Home>
{
    public override void WriteJson(JsonWriter writer, Home value, JsonSerializer serializer)
    {
        var jsonObj = new JObject();
        jsonObj.Add("Id", value.Id);
        jsonObj.Add(value.propertyName, value.Text);
        jsonObj.WriteTo(writer);
    }

    // 反序列化逻辑会在后面讲
    public override Home ReadJson(JsonReader reader, Type objectType, Home existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        var home = new Home();
        home.Id = jObj.GetValue("Id").Value<int>();
        // 提取除Id外的动态属性
        var dynamicProp = jObj.Properties().First(p => p.Name != "Id");
        home.propertyName = dynamicProp.Name;
        home.Text = dynamicProp.Value.Value<string>();
        return home;
    }
}

使用转换器序列化:

var json = JsonConvert.SerializeObject(home, new HomeConverter());

System.Text.Json 自定义转换器

public class HomeJsonConverter : JsonConverter<Home>
{
    public override void Write(Utf8JsonWriter writer, Home value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteNumber("Id", value.Id);
        writer.WriteString(value.propertyName, value.Text);
        writer.WriteEndObject();
    }

    // 反序列化逻辑会在后面讲
    public override Home Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var home = new Home();
        home.Id = root.GetProperty("Id").GetInt32();
        // 遍历找到动态属性
        foreach (var prop in root.EnumerateObject())
        {
            if (prop.Name != "Id")
            {
                home.propertyName = prop.Name;
                home.Text = prop.Value.GetString();
                break;
            }
        }
        return home;
    }
}

使用转换器序列化:

var options = new JsonSerializerOptions { Converters = { new HomeJsonConverter() } };
var json = JsonSerializer.Serialize(home, options);

二、最佳反序列化方式

反序列化的核心是识别出JSON中除Id之外的那个动态属性,把它的名称赋值给propertyName,值赋值给Text。这里推荐自定义Json转换器作为最佳方案,原因如下:

  • 逻辑统一:同一个转换器可以同时处理序列化和反序列化,避免代码冗余
  • 类型安全:相比手动解析字典,转换器能更可靠地处理类型转换,减少出错概率
  • 扩展性强:如果后续类结构有变化,只需要修改转换器逻辑即可

当然,如果是非常简单的场景,也可以先反序列化成字典再手动映射:

Newtonsoft.Json 字典映射方式

var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var home = new Home
{
    Id = (int)dict["Id"],
    propertyName = dict.Keys.First(k => k != "Id"),
    Text = (string)dict[dict.Keys.First(k => k != "Id")]
};

System.Text.Json 字典映射方式

var dict = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
var home = new Home
{
    Id = Convert.ToInt32(dict["Id"]),
    propertyName = dict.Keys.First(k => k != "Id"),
    Text = dict[dict.Keys.First(k => k != "Id")] as string
};

但这种方式在对象结构复杂或有多个动态属性时,容易出现空引用或类型转换错误,所以还是优先选择自定义转换器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:39:43