我有一个类,它呈现如下
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 序列化属性的列表。