C# 基类序列化问题-不序列化派生类属性
我已经厌倦了序列化一个相当大的实体列表,这些实体都是从基类派生的。 我只需要客户端中的基类属性。如何在不实例化基类的新实例的情况下实现这一点 我曾尝试创建一个自定义ContractResolver,但它似乎在运行时执行getType(),而不是使用正在序列化的列表/数组的类型 请参阅下面的代码示例 我想要实现。castBaseString==actualBaseString 所以我希望castBaseString=C# 基类序列化问题-不序列化派生类属性,c#,.net,json.net,C#,.net,Json.net,我已经厌倦了序列化一个相当大的实体列表,这些实体都是从基类派生的。 我只需要客户端中的基类属性。如何在不实例化基类的新实例的情况下实现这一点 我曾尝试创建一个自定义ContractResolver,但它似乎在运行时执行getType(),而不是使用正在序列化的列表/数组的类型 请参阅下面的代码示例 我想要实现。castBaseString==actualBaseString 所以我希望castBaseString=[{“Id”:1},{“Id”:2}]而不是[{“Value”:“Value”,“
[{“Id”:1},{“Id”:2}]
而不是[{“Value”:“Value”,“Id”:1},{“Value”:“value2”,“Id”:2}]
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Tests {
[TestClass]
public class JsonNetTest {
class Base {
public int Id { get; set; }
}
class Derived : Base {
public string Value { get; set; }
}
class OtherDerived : Base {
public string Value { get; set; }
public string OtherValue { get; set; }
}
[TestMethod]
public void Test() {
IEnumerable<Derived> deriveds = new Derived[] {
new Derived {Id = 1, Value = "value" },
new Derived {Id = 2, Value = "value2" }
};
IEnumerable<Base> castBases = deriveds.Cast<Base>().ToList();
IEnumerable<Base> bases = new Base[] {
new Base {Id = 1 },
new Base {Id = 2 }
};
JsonSerializerSettings s = new JsonSerializerSettings();
var derString = JsonConvert.SerializeObject(deriveds, s);
var castBaseString = JsonConvert.SerializeObject(castBases, s);
var actualBaseString = JsonConvert.SerializeObject(bases, s);
Assert.AreEqual(actualBaseString, castBaseString);
Assert.AreNotEqual(castBaseString, derString);
}
}
}
使用System.Linq;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用System.Collections.Generic;
使用Newtonsoft.Json;
命名空间测试{
[测试类]
公共类JSONNETSET{
阶级基础{
公共int Id{get;set;}
}
派生类:基{
公共字符串值{get;set;}
}
类:基{
公共字符串值{get;set;}
公共字符串OtherValue{get;set;}
}
[测试方法]
公开无效测试(){
IEnumerable-deriveds=新派生[]{
新派生的{Id=1,Value=“Value”},
新派生的{Id=2,Value=“value2”}
};
IEnumerable castBases=deriveds.Cast().ToList();
IEnumerable Base=新基[]{
新基{Id=1},
新基{Id=2}
};
JsonSerializerSettings s=新的JsonSerializerSettings();
var derString=JsonConvert.SerializeObject(deriveds,s);
var castBaseString=JsonConvert.SerializeObject(castBases,s);
var actualBaseString=JsonConvert.SerializeObject(基数,s);
AreEqual(actualBaseString、castBaseString);
arenetQual(castBaseString、derString);
}
}
}
根据评论进行编辑
附加上下文:为了清晰起见,我刚刚发布了这个简单的测试用例。 实际使用的上下文是在aspnet核心应用程序中 假设有3个控制器
希望这能澄清。添加
[JsonIgnore]
属性顶部
class Derived : Base {
[JsonIgnore]
public string Value { get; set; }
}
如果不想使用属性,可以使用ContractResolver强制仅序列化
Base
中的属性:
public类派生的TypeFilterContractResolver:DefaultContractResolver{
受保护的重写JsonProperty CreateProperty(MemberInfo成员、MemberSerialization MemberSerialization){
JsonProperty属性=base.CreateProperty(成员,成员序列化);
if(property.DeclaringType!=typeof(T)){
property.ShouldSerialize=instance=>false;
}
归还财产;
}
}
然后像这样使用它:
void Main(){
IEnumerable-deriveds=新派生[]{
新派生的{Id=1,Value=“Value”},
新派生的{Id=2,Value=“value2”}
};
IEnumerable castBases=deriveds.Cast().ToList();
IEnumerable Base=新基[]{
新基{Id=1},
新基{Id=2}
};
JsonSerializerSettings s=新的JsonSerializerSettings{
ContractResolver=新的DerivedTypeFilterContractResolver()
};
var derString=JsonConvert.SerializeObject(deriveds,s);
var castBaseString=JsonConvert.SerializeObject(castBases,s);
var actualBaseString=JsonConvert.SerializeObject(基数,s);
Console.WriteLine(castBaseString);
}
阶级基础{
公共int Id{get;set;}
}
派生类:基{
公共字符串值{get;set;}
}
输出:
[{“Id”:1},{“Id”:2}]
结果表明,json序列化的工作方式不可能做到这一点。
@stuartd answer可能是一个很好的解决方法,如果您只想处理有限的情况。另一个选项是使用
[JsonObject(MemberSerialization=MemberSerialization.OptIn)]为派生的类添加属性,默认情况下排除所有属性(无需使用jsoninoreattribute标记它们)。对于其他特定调用,我确实希望序列化该值,但在序列化基类时不这样做。此外,由于它是第三方数据模型,因此我没有向正在使用的类型添加属性的选项。这一切都很好,但现在第二个断言失败,因为在序列化派生时,它将它们序列化为“[{“Id”:1},{“Id”:2}]”,省略派生的.Value字段。另外,如果您现在序列化任何其他不是从Base派生的对象,那么它们都将是“[{},{}]”好的,是的。只有当您只需要基类值时,才可以使用此解析器。有没有关于如何在aspnet核心项目中实现这一点的想法。我非常确定契约解析器在启动时被缓存,并且由于性能原因,您不能在运行时更改它。我会看看这样的东西是否有效:关于如何在aspnet核心项目中做到这一点,有什么想法吗你必须提供更多的细节。您问我,我正在尝试序列化一个相当大的实体列表,这些实体都是从基类派生的。我只需要客户端中的基类属性。使用这个契约解析器就可以做到这一点。但现在你是说你只想这么做