gpt4 book ai didi

c# - 序列化和反序列化不适用于字典作为支持字段

转载 作者:行者123 更新时间:2023-12-04 09:28:04 27 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Why are all the collections in my POCO are null when deserializing some valid json with the .NET Newtonsoft.Json component

(1 个回答)



Set accessor not being called when I deserialise object from Json.net

(1 个回答)


1年前关闭。




当隐藏在属性后面的支持字段中时,我遇到了一个字典的序列化/反序列化的奇怪问题。
这是 fiddle :
https://dotnetfiddle.net/RFZEur
最终结果:

  • 语言: C#
  • 框架: .Net 框架 4.8
  • 有一个私有(private)支持领域 配对的组合
  • 可以序列化为字符串列表 (不包括整数,指向引用的支持字段)
  • 不能是从序列化列表中反序列化 -- 支持字典不会被填充。

  • public class SanityChecks
    {
    private readonly ITestOutputHelper _testOutputHelper;
    public SanityChecks(ITestOutputHelper testOutputHelper)
    {
    _testOutputHelper = testOutputHelper;
    }
    public class TestClass
    {
    [JsonIgnore]
    public Dictionary<int,string> _prvList = new Dictionary<int, string>();
    public IEnumerable<string> ListValues
    {
    get => _prvList.Select(p=> p.Value).ToList();
    set
    {
    var valArr = value.ToArray();
    for (var x = 0; x < valArr.Length; x++)
    {
    _prvList.Add(x,valArr[x]);
    }
    }
    }
    }
    [Fact]
    public void SanityCheck_CanDeserialize()
    {
    var assumption = "{\"ListValues\":[\"TestValue\",\"AAA\"]}";
    var actual = JsonConvert.DeserializeObject<TestClass>(assumption);
    Assert.Equal(2, actual._prvList.Count());
    Assert.Equal(2, actual.ListValues.Count());
    }
    [Fact]
    public void SanityCheck_CanSerialize()
    {
    var assumption = new TestClass() { ListValues = new[] { "TestValue", "AAA" } };
    var actualSerialized = JsonConvert.SerializeObject(assumption);
    _testOutputHelper.WriteLine(actualSerialized);
    Assert.Equal("{\"ListValues\":[\"TestValue\",\"AAA\"]}", actualSerialized);
    }
    [Fact]
    public void SanityCheck_CanDeserializeFromSerialized()
    {
    var assumption = new TestClass() { ListValues = new[] { "TestValue", "AAA" } };
    var actualSerialized = JsonConvert.SerializeObject(assumption);
    _testOutputHelper.WriteLine(actualSerialized);
    var actualDeserialized = JsonConvert.DeserializeObject<TestClass>(actualSerialized);
    Assert.Equal(2, actualDeserialized._prvList.Count());
    var actualDeserializedSerialized = JsonConvert.SerializeObject(actualDeserialized);
    _testOutputHelper.WriteLine(actualDeserializedSerialized);
    Assert.Equal(actualSerialized, actualDeserializedSerialized);
    }
    }
    如果您对如何检索此结果有一些建议,我很乐意。我使用 XUnit 进行测试,但是 fiddle 快速实现了下面的测试,稍作修改使其成为控制台应用程序。
    我尝试了 ISerializable 的实现进入对象,但是我遇到了同样的问题。
    值得注意的怪事: 移除 IEnumerable 中的 Get 子句导致反序列化工作(序列化不再工作)
    编辑:
    为了更加清楚,我需要将 int,string 配对的映射序列化为字符串列表,并且我需要将相同的序列化版本反序列化为 int,string 配对的集合。
    对于 fiddle :不应该抛出异常
    对于 XUnit:所有测试都应该通过。

    最佳答案

    原因是ListValues反序列化后 enumerable 为空的原因如下:

  • 默认情况下,Json.Net 将在反序列化期间重用现有对象值,而不是创建新对象值。因此,对于 ListValues 等属性,它将首先调用访问器,然后找到现有列表,然后继续从 JSON 中填充它。
  • ListValues 的访问者每次都不会返回相同的列表实例;它总是从 _prvList 创建一个新实例支持领域。

  • 因此,在反序列化过程中会发生以下情况:
  • 序列化程序调用 ListValues访问器,它返回从字典创建的新空列表。
  • 序列化程序从 JSON 填充该列表。
  • 填充的列表被丢弃(序列化程序假定 TestClass 实例已经具有对列表的引用,因此它永远不会调用 mutator)。
  • 当测试稍后调用 ListValues访问器,它返回一个新的空列表,再次从字典创建。

  • 您可以通过设置 ObjectCreationHandling 来更改序列化程序的行为。设置为 Replace .在反序列化期间应用此设置可让您的测试通过。 fiddle here .

    关于c# - 序列化和反序列化不适用于字典作为支持字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62941934/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com