我有以下类型:
public class Product : Dictionary<string, object>
{
[JsonInclude]
public string ProductId { get; set; }
public Product(string productId) : base()
{
ProductId = productId;
}
}
使用 System.Text.Json 进行序列化时,它不包含属性(即 ProductId
)。
添加或删除 [JsonInclude]
似乎没有任何效果。
测试用例:
[Fact]
public void SimpleTest()
{
var p = new Product("ABC123");
p["foo"] = "bar";
var json = JsonSerializer.Serialize(p);
Assert.Contains("productId", json, StringComparison.OrdinalIgnoreCase);
}
并收到输出:
{"foo":"bar"}
如何让它在序列化期间将我的自定义属性包含在我的类型中? (注意:不要关心反序列化)。
最佳答案
System.Text.Json
不序列化字典属性。
我在 MSFT 文档中找不到任何地方说明了这一点,但是 System.Text.Json
仅序列化字典键和值。这可以从 DictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>
的引用来源得到证实。 ,这是用于您的类型的转换器。
这可能是因为:
- 可能存在与属性同名的键。
- 应用程序开发人员几乎肯定不想要像
Count
这样的“标准”字典属性和IsReadOnly
将被连载。 - 早期序列化器的行为方式与
System.Text.Json
相同正在遵循先例。 Newtonsoft 是 documented to only serialize dictionary keys and values .DataContractJsonSerializer
(与UseSimpleDictionaryFormat = true
)和JavaScriptSerializer
也做。
作为替代方案,您可以考虑使用不同的数据模型,其中 Product
不继承自 Dictionary
而是有一个 [JsonExtensionData] public Dictionary<string, object> Properties { get; set; }
属性:
public class Product
{
public string ProductId { get; set; }
[System.Text.Json.Serialization.JsonExtensionData]
public Dictionary<string, object> Properties { get; set; } = new ();
public Product(string productId) : base()
{
ProductId = productId;
}
}
[JsonExtensionData]
属性导致字典属性在序列化和反序列化时作为父对象的一部分包含在内。
注意事项:
如果建议的替代方案 Not Acceptable ,您将需要编写自定义
JsonConverter
手动序列化您的Product
的 .NET 属性以及键和值词典。正在添加
[JsonInclude]
至ProductId
不会强制它序列化。根据docs forJsonInclude
, 当应用于属性时,[它] 表示非公共(public) getter 和 setter 可用于序列化和反序列化。 因此它与此处无关ProductId
已经有公共(public) getter 和 setter。Newtonsoft 也有一个
JsonExtensionData
属性(做同样的事情)。如果您同时使用这两种序列化程序,请小心使用正确的属性。在您的问题中,您声明不关心反序列化,但反序列化确实可以与
JsonExtensionData
一起正常工作.
演示 fiddle here .
关于c# - 使用 System.Text.Json 的自定义类型继承 Dictionary 的序列化不会序列化其他属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69201788/