如何在继承的 ICollection 类中序列化属性<T>?



我有一个类,它呈现如下

public class ItemCollection<T> : ICollection<T> {
public ItemCollection() {
Items = new List<T>();
}
public List<T> Items { get; set; }
...
}

现在它将被序列化为:

{
"Property": [{...}]
}

但我希望结果是这样的:

{
"Property": {"Items": [{...}]}
}

很抱歉缺少这个问题的信息。

我现在在使用System.Text.Json时陷入序列化。

在Newtonsoft.Json中,我使用[JsonObject]来注释这个类,以便它可以正确地序列化为带有"Items": value的json,但我不知道如何使用System.Text.Json序列化Items属性。

我有一些类继承了这个类,继承将作为其他类的属性。

溶液:

感谢您回答这个问题的每个人,我找到了解决此问题的解决方案。我创建了一个ConverterFactory来解析创建转换器所需的类型。在转换器中,我创建新的JsonObject并使用Reflection在类型中创建属性,之后,我序列化JsonObject以便获得正确的结果。

谢谢你的提问,但我没有发现Newtonsoft和System.Text.Json的序列化之间有任何区别。

也许您可以在代码中提供一个示例来直接向我们展示问题。 使用您提供的信息,我通过以下代码示例获得了相同的结果

static void Main(string[] args)
{
ItemCollection<Person> list = new ItemCollection<Person> {new Person(){ FirstName = "FirstName", Name = "Name"}};
string jsonString = JsonSerializer.Serialize(list);
Console.WriteLine(jsonString);

string jsonString2 =Newtonsoft.Json.JsonConvert.SerializeObject(list);
Console.WriteLine(jsonString2);
Console.ReadLine();
}

[{"名称":"名称","名字":"名字"}]

没有与Newtonsoft的JsonObjectAttribute相对应的内置属性,该属性将强制将集合序列化为JSON对象。1.并且没有可以覆盖IContractResolver的公共等价物来自定义序列化元数据。 因此,您需要创建自定义JsonConverter来序列化ItemCollection<T>的属性,如下所示:

[System.Text.Json.Serialization.JsonConverter(typeof(ItemCollectionJsonConverter))]
public partial class ItemCollection<T> : ICollection<T> {
internal ItemCollection(List<T> items) { // I added this for use by the converter
Items = items ?? throw new ArgumentNullException();
}
public ItemCollection() {
Items = new List<T>();
}
public List<T> Items { get; set; }
// Remainder omitted
}
public class ItemCollectionJsonConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert) => GetItemCollectionValueType(typeToConvert) != null;
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
=> (JsonConverter)Activator.CreateInstance(typeof(ItemCollectionJsonConverterInner<>).MakeGenericType(GetItemCollectionValueType(type)!))!;
static Type? GetItemCollectionValueType(Type type) =>
(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ItemCollection<>)) ? type.GetGenericArguments()[0] : null;
class ItemCollectionJsonConverterInner<T> : JsonConverter<ItemCollection<T>>
{
class ItemCollectionDTO
{
public List<T>? Items { get; set; }
// Add other properties here
}

public override ItemCollection<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
// TODO: Decide whether to throw on null
new ItemCollection<T>((JsonSerializer.Deserialize<ItemCollectionDTO>(ref reader, options)?.Items) ?? throw new JsonException());

public override void Write(Utf8JsonWriter writer, ItemCollection<T> value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, new ItemCollectionDTO { Items = value.Items }, options);
}
}

笔记:

  • 我通过属性直接将转换器添加到ItemCollection<T>,但如果您愿意,可以将其添加到JsonSerializerOptions.Converters

  • 许多序列化程序不会序列化集合属性。 例如,请参阅 XmlSerializer 不会为另一个类序列化我类中的所有内容

  • 集合添加属性并不是真正推荐的做法;有关原因的讨论,请参阅为什么不从 List继承。

演示小提琴在这里。


1此处记录了所有 System.Text.Json 序列化属性的列表。

相关内容

  • 没有找到相关文章

最新更新