[英]How can I serialize a property in an inherited ICollection<T> class?
I have a class that presented like我有一个 class 像
public class ItemCollection<T> : ICollection<T> {
public ItemCollection() {
Items = new List<T>();
}
public List<T> Items { get; set; }
...
}
Now it will be serialized into:现在它将被序列化为:
{
"Property": [{...}]
}
But I want the result is like:但我想要的结果是这样的:
{
"Property": {"Items": [{...}]}
}
Sorry for the missing information of this question.抱歉,这个问题缺少信息。
I now stuck in serialization when using System.Text.Json.我现在在使用 System.Text.Json 时陷入序列化。
In Newtonsoft.Json, I use [JsonObject]
to annotate this class so it can serialization correctly into json with "Items": value
, but I don't know how to serialize the Items
property using System.Text.Json. In Newtonsoft.Json, I use
[JsonObject]
to annotate this class so it can serialization correctly into json with "Items": value
, but I don't know how to serialize the Items
property using System.Text.Json.
I have some classes inherited this class and the inheritances will be as properties in other classes.我有一些类继承了这个 class 并且继承将作为其他类中的属性。
Solution:解决方案:
Thank you for every one that answered this question, I have found a solution to solve this.感谢每个回答这个问题的人,我已经找到了解决这个问题的方法。 I create a
ConverterFactory
to resolve the needed types to create the converters.我创建了一个
ConverterFactory
来解析创建转换器所需的类型。 In the converter, I create new JsonObject
and use Reflection
to create the properties in the type, after this, I serialize the JsonObject
so I can get the correct result.在转换器中,我创建了新的
JsonObject
并使用Reflection
来创建类型中的属性,之后,我序列化了JsonObject
以便获得正确的结果。
Thank you for your question, but I did not found any difference between the serialization of Newtonsoft and System.Text.Json.谢谢你的提问,但是我没有发现 Newtonsoft 和 System.Text.Json 的序列化有什么区别。
Perhabs you can provide an example in code to show us the problem directly.也许您可以在代码中提供一个示例来直接向我们展示问题。 With your provided information I got with following code example the same results
根据您提供的信息,我通过以下代码示例获得了相同的结果
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();
}
[{"Name":"Name","FirstName":"FirstName"}] [{"姓名":"姓名","名":"名"}]
There is no built-in attribute corresponding to Newtonsoft's JsonObjectAttribute
that will force a collection to be serialized as a JSON object.没有对应于 Newtonsoft 的
JsonObjectAttribute
的内置属性将强制将集合序列化为 JSON object。 1 . 1 . And there is no public equivalent to
IContractResolver
that can be overridden to customize serialization metadata.并且没有可以重写以自定义序列化元数据的
IContractResolver
的公共等效项。 Thus you will need to create a custom JsonConverter
to serialize the properties of your ItemCollection<T>
, such as the following:因此,您需要创建一个自定义
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);
}
}
Notes:笔记:
I added the converter directly to ItemCollection<T>
via attributes, but you could add it to JsonSerializerOptions.Converters
if you prefer.我通过属性直接将转换器添加到
ItemCollection<T>
,但如果您愿意,可以将其添加到JsonSerializerOptions.Converters
。
Many serializers will not serialize collection properties.许多序列化程序不会序列化集合属性。 See eg XmlSerializer doesn't serialize everything in my class for another.
参见例如XmlSerializer 不会序列化我的 class中的所有内容。
Adding properties to collections isn't really a recommended practice;向 collections 添加属性并不是真正推荐的做法。 see Why not inherit from List<T>?
请参阅为什么不从 List<T> 继承? for a discussion why.
讨论为什么。
1 The list of all System.Text.Json serialization attributes is documented here . 1 此处记录了所有 System.Text.Json 序列化属性的列表。
just add object in Serialize method只需在序列化方法中添加 object
var jsonMessageBody = JsonSerializer.Serialize<object>(model);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.