【发布时间】:2020-07-16 19:09:29
【问题描述】:
当字典隐藏在属性后面的支持字段中时,我遇到了一个奇怪的字典序列化/反序列化问题。
这是小提琴: https://dotnetfiddle.net/RFZEur
最终结果:
- 语言:C#
- 框架:.Net Framework 4.8
- 有一个 私有支持字段,它与
组合成对 - 可以序列化为字符串列表(不包括整数,指向引用的支持字段)
- 无法从序列化列表中反序列化 - 不填充支持字典。
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 进行测试,但是小提琴快速实现了下面的测试,稍作修改使其成为控制台应用程序。
我尝试在对象中实现ISerializable,但遇到了同样的问题。
注意的奇怪之处:删除 IEnumerable 中的 Get 子句会导致反序列化工作(序列化不再工作)
编辑: 为了更加清楚,我需要将 int,string 配对的映射序列化为字符串列表,并且我需要将相同的序列化版本反序列化为 int,string 配对的集合。
对于小提琴:不应该抛出异常 对于 XUnit:所有测试都应该通过。
【问题讨论】:
-
非常不清楚您的问题是什么-感谢您提供minimal reproducible example,但是您仍然需要解释您想要实现的目标...无法实现您想要的代码不能单独显示那个(即在这种特殊情况下,非常不清楚您希望如何反序列化只读类型)。
-
@AlexeiLevenkov 谢谢!我会添加一些清晰度,我以为我很清楚。我需要一个私有的
配对被外部序列化为字符串列表(忽略 int)并从字符串列表反序列化为 配对(基于索引生成的 INT) 两个对象都没有被读取- 仅限。 -
看看this answer。
IEnumerable的默认序列化使用List,但您的测试代码构建 arrays。因此,生成的 JSON 可能包含"$type": "System.String[], mscorlib"以表明它是数组类型,而不是 List。我自己没有运行过你的测试,但我怀疑这可能是它失败的原因,因为你的硬编码 JSON 字符串不包含数组类型。该链接中的另一个答案建议使用属性[JsonProperty(TypeNameHandling = TypeNameHandling.None)]来避免这种情况。 -
@SeanSkelly 我尝试了提供的解决方案 [JsonProperty(TypeNameHandling = TypeNameHandling.None)] 相同的结果。我决定尝试文档中引用的其他一些接口,相同的复制结果:(尽管读得很好!查看引用的溢出页面,它处理了 IList、List 和对象数组的行为差异,原因是序列化为数组,但预期类型是 List。根据相同的文档,它需要 IEnumerable
实现,在定义的对象内。 -
set { var valArr = value.ToArray(); for (var x = 0; x < valArr.Length; x++) { _prvList.Add(x,valArr[x]); } }很奇怪。看起来您只允许调用一次设置器(因为使用相同的数据调用它两次将返回由于Add而导致的第二次调用异常)?如果键始终是索引,为什么不使用List作为后备存储(因为它内置了索引)?
标签: c# json serialization json.net deserialization