如何使用System.Text.json正确地反序列化具有IReadOnlyCollection的类< T>?

wswtfjt7  于 2023-04-13  发布在  其他
关注(0)|答案(2)|浏览(125)

我有以下类:

public sealed class SomeClass
{
    [JsonConstructor()]
    public SomeClass(IEnumerable<string> myItems)
    {
        InternalMyItems = new Collection<string>(myItems.ToArray());
        MyItems = new ReadOnlyCollection<string>(InternalMyItems);
    }
    
    public IReadOnlyCollection<string> MyItems { get; }
    private Collection<string> InternalMyItems { get; }
}

序列化似乎工作正常:

{
  "MyItems": [
    "A",
    "B",
    "C"
  ]
}

反序列化似乎不起作用。理想情况下,我希望坚持使用ReadOnlyCollection<T>Collection<T>,而不必更改为其他类型。此示例代码在尝试反序列化时抛出异常:

var options = new JsonSerializerOptions()
{
    WriteIndented = true
};

var items = new[] { "A", "B", "C" };
var instance = new SomeClass(items);

var json = JsonSerializer.Serialize(instance, options);

var copy = JsonSerializer.Deserialize<SomeClass>(json, options);

InvalidOperationException:类型“UserQuery+SomeClass”的反序列化构造函数中的每个参数在反序列化时必须绑定到对象属性或字段。每个参数名称必须与对象上的属性或字段匹配。仅当启用“JsonSerializerOptions.IncludeFields”时才考虑字段。匹配可以不区分大小写。
下面是一个.NET Fiddle代码运行并给出错误的例子:https://dotnetfiddle.net/vorOLX

anauzrmj

anauzrmj1#

构造函数参数的类型和名称必须与类中的属性匹配。System.Text.Json还知道如何直接构造IReadOnlyCollection<T>,因此只需使用该类型。例如,您可以简单地执行以下操作:

public sealed class SomeClass
{
    [JsonConstructor]
    public SomeClass(IReadOnlyCollection<string> myItems)
                   // ^^^^ matching type         
    {
        MyItems = myItems;
    }

    public IReadOnlyCollection<string> MyItems { get; }
}
roejwanj

roejwanj2#

关于docs
参数化构造函数的参数名必须与属性名和类型匹配。
您可以尝试使用IReadOnlyCollection并匹配类型:

public sealed class SomeClass
{
    [JsonConstructor()]
    public SomeClass(IReadOnlyCollection<string> myItems)
    {
        InternalMyItems = new Collection<string>(myItems.ToArray());
        this.MyItems = new ReadOnlyCollection<string>(InternalMyItems);
    }

    public IReadOnlyCollection<string> MyItems { get; }
    private Collection<string> InternalMyItems { get; }
}

如果需要,您可以保留原始文件:

public sealed class SomeClass
{
    [System.Text.Json.Serialization.JsonConstructor()]
    public SomeClass(IReadOnlyCollection<string> myItems)
    {
        InternalMyItems = new Collection<string>(myItems.ToArray());
        this.MyItems = new ReadOnlyCollection<string>(InternalMyItems);
    }

    public SomeClass(IEnumerable<string> myItems)
    {
        InternalMyItems = new Collection<string>(myItems.ToArray());
        MyItems = new ReadOnlyCollection<string>(InternalMyItems);
    }

    public IReadOnlyCollection<string> MyItems { get; }
    private Collection<string> InternalMyItems { get; }
}

相关问题