【发布时间】:2021-06-23 16:04:23
【问题描述】:
假设你有:
class ContentRef {
SomeProperty
}
class Content : ContentRef {
SomeOtherProperty
}
class C {
ContentRef someProperty;
List<ContentRef> someList;
}
var someObject = new C { someProperty = new Content(), someList = new List<ContentRef>({new Content()})};
默认情况下,Newtonsoft 和 System.Text.Json 都会序列化 someObject 中 Content 的所有属性。但很明显,C 的定义说两者都是 A 类型。我想确保在直接属性 A 和 List 的情况下,即使您将 B 分配给它,唯一被序列化的是 A 的属性。
当您为正在设置的属性设置一个 Ref 类并将其设置为从其余数据的 ref 类继承的完整类时,这种情况在文档数据库中一直发生。您只希望文档数据库存储 ref 类的数据,而不是整个类的所有数据,因为当它被反序列化时,您只关心定义的 Ref 类。
我有这个:
public class StrictTypeContractResolver : DefaultContractResolver
{
private readonly FieldInfo _IsSealedField = typeof(JsonContract).GetField("IsSealed", BindingFlags.Instance | BindingFlags.NonPublic)!;
public override JsonContract ResolveContract(Type type)
{
var resolveContract = base.ResolveContract(type);
_IsSealedField.SetValue(resolveContract, true);
return resolveContract;
}
}
这适用于直接属性情况,仅序列化实际定义的类型。但是,我不知道如何让它在 List 类型(哈希集、IList 或 IEnumerable)上工作。它序列化整个事物,而不是像它应该的那样序列化 List。
【问题讨论】:
-
有些合约解析器会忽略基本类型成员 here 和 here。您可以检查这些是否适合您,如果不适合,请分享minimal reproducible example 吗?您的
ContentRef示例似乎是伪代码,因此我不清楚您在哪里遇到问题。 -
另外,为什么同时标记system.text.json 和json.net?
System.Text.Jsondoesn't even have a publicly facing contract resolver 所以答案会完全不同。 -
这不是我想忽略的基本类型。当属性或列表元素类型是基本类型时,我想忽略继承的类型属性,并且应该将其反序列化为属性的定义类型,而不是传入的任何内容。它就像设置定义为 ContentRef 的属性一样简单内容将导致它与所有内容而不是 ContentRef 一起序列化,并且它应该忽略其余的并且只有序列化 ContentRef。更糟糕的是,即使类型已明确定义,它也会对列表元素执行此操作。所以我正在尝试撤消这种荒谬的行为。
-
Ps:json.net 和 System.Text.Json 都表现出相同的荒谬行为,并忽略您的类型定义并序列化子类型而不是定义的基类型。
-
我认为自动序列化派生类型的属性一点也不荒谬。事实上,它是首选。假设您有一个包含形状列表的 Canvas 类。基本形状在画布上具有名称属性和位置。但是每个衍生形状都有定义它的特定属性——例如,圆形有一个中心和半径,而多边形有一系列顶点。如果我要序列化 Canvas,我绝对希望形状的细节也被序列化,否则我将无法从 JSON 重建完整的 Canvas!
标签: c# json.net system.text.json