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

如何在C#中用System.Text.Json正确序列化带命名元组的List

解决ValueTuple序列化JSON显示空对象的问题

嘿,这个问题我之前也碰到过!核心原因是System.Text.Json默认不认命名ValueTuple的自定义字段名——你虽然写了(string oid,string data,string desc),但在底层,ValueTuple的实际字段是Item1、Item2、Item3,oid、data、desc只是编译时的别名,序列化器根本识别不了这些别名,再加上默认配置可能忽略了未公开的字段,所以就输出空的{}了。

下面给你几个实用的解决办法,按需选就行:

方法1:改用普通数据类(最推荐)

最稳妥的方式是把ValueTuple换成一个简单的数据类,这样序列化器能直接识别字段/属性名,后续维护也更方便:

// 定义一个专门的资产项类
public class AssetItem
{
    public string Oid { get; set; }
    public string Data { get; set; }
    public string Desc { get; set; }
}

// 把Asset类里的列表改成这个类型
public List<AssetItem> assetData { get; set; }

之后用你原来的序列化代码,就能正常输出带字段名的JSON了,完全不用额外配置。

方法2:给ValueTuple写自定义转换器

如果你不想改现有数据结构,可以写一个自定义JsonConverter来处理这个命名元组:

public class AssetTupleConverter : JsonConverter<(string oid, string data, string desc)>
{
    // 反序列化逻辑(如果需要反序列化的话)
    public override (string oid, string data, string desc) Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        return (
            root.GetProperty("oid").GetString()!,
            root.GetProperty("data").GetString()!,
            root.GetProperty("desc").GetString()!
        );
    }

    // 序列化时手动写入我们想要的字段名
    public override void Write(Utf8JsonWriter writer, (string oid, string data, string desc) value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteString("oid", value.oid);
        writer.WriteString("data", value.data);
        writer.WriteString("desc", value.desc);
        writer.WriteEndObject();
    }
}

然后在序列化的时候注册这个转换器就行:

private static void Serialize(Asset asset, JsonSerializerOptions? options = null)
{
    var opts = options ?? new JsonSerializerOptions()
    {
        WriteIndented = true,
        IgnoreNullValues = true,
    };
    // 添加自定义转换器
    opts.Converters.Add(new AssetTupleConverter());

    var json = JsonSerializer.Serialize<Asset>(asset, opts);
    Console.WriteLine(json);
}

方法3:切换到Newtonsoft.Json(Json.NET)

如果项目允许换JSON库,Newtonsoft.Json对命名ValueTuple的支持要友好得多,默认就能识别你定义的oid、data、desc别名:

先通过NuGet安装Newtonsoft.Json包,然后修改序列化代码:

private static void Serialize(Asset asset)
{
    var json = JsonConvert.SerializeObject(asset, Formatting.Indented, new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore
    });
    Console.WriteLine(json);
}

这种方式完全不用改你的assetData列表类型,直接就能输出符合预期的JSON。

小提醒

看你提供的数据示例,有些Data字段是空的,比如第一条OID= 1.3.6.1.2.1.1.1.0对应的Data是空值,因为你设置了IgnoreNullValues = true,这些空值字段会被序列化器忽略,如果希望保留的话,可以把这个配置去掉。

另外要确保你的assetData里每个元组的desc成员都正确赋值了(比如对应示例里的BGP4-V2-MIB::bgpM2BaseNotifications),不然也会被忽略哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:24:19