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

.NET 8中Statistics<T>类的System.Text.Json序列化反序列化问题

解决方案:让Statistics实现IDictionary<int, T>接口

要让Statistics<T>的序列化/反序列化格式与Dictionary<int, T>完全一致,且无需修改外部调用方的JsonSerializerOptions,只需修改Statistics<T>类本身,让它实现IDictionary<int, T>接口——System.Text.Json会默认将实现该接口的类型以字典格式(JSON键值对对象)处理,和原生Dictionary的输出完全匹配。

修改后的完整类代码:

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

namespace SerializeCustomEnumerable;

public class Statistics<T> : IEnumerable<(int Year, T Value)>, IDictionary<int, T> where T : new()
{
    // 添加[JsonInclude]让序列化器能访问protected成员,用于反序列化重建
    [JsonInclude]
    protected Dictionary<int, T> Years { get; set; } = new Dictionary<int, T>();
    
    public Statistics() { }

    public Statistics(Dictionary<int, T> years)
    {
        Years = years ?? throw new ArgumentNullException(nameof(years));
    }

    public T this[int year]
    {
        get
        {
            return Years.TryGetValue(year, out var value) ? value : new T();
        }
        set
        {
            Years[year] = value;
        }
    }

    // 直接委托底层Years字典实现IDictionary接口成员
    public ICollection<int> Keys => Years.Keys;
    public ICollection<T> Values => Years.Values;
    public int Count => Years.Count;
    public bool IsReadOnly => false;

    public void Add(int key, T value) => Years.Add(key, value);
    public bool ContainsKey(int key) => Years.ContainsKey(key);
    public bool Remove(int key) => Years.Remove(key);
    public bool TryGetValue(int key, out T value) => Years.TryGetValue(key, out value);
    public void Add(KeyValuePair<int, T> item) => Years.Add(item.Key, item.Value);
    public void Clear() => Years.Clear();
    public bool Contains(KeyValuePair<int, T> item) => Years.Contains(item);
    public void CopyTo(KeyValuePair<int, T>[] array, int arrayIndex) => ((ICollection<KeyValuePair<int, T>>)Years).CopyTo(array, arrayIndex);
    public bool Remove(KeyValuePair<int, T> item) => ((ICollection<KeyValuePair<int, T>>)Years).Remove(item);

    // 保留原有枚举逻辑
    public IEnumerator<(int Year, T Value)> GetEnumerator()
    {
        foreach (var element in Years)
        {
            yield return (element.Key, element.Value);
        }
    }

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    IEnumerator<KeyValuePair<int, T>> IEnumerable<KeyValuePair<int, T>>.GetEnumerator() => Years.GetEnumerator();
}

关键说明:

  • 实现IDictionary<int, T>后,System.Text.Json自动以字典格式序列化/反序列化,输出与Dictionary<int, T>完全一致的JSON。
  • [JsonInclude]确保protected的Years字段能被序列化器访问,反序列化时正确重建对象。
  • 所有ID接口方法直接委托给底层字典,无需额外逻辑,保留原有类的全部功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:07:51