C#Serialize没有基本属性的继承类

时间:2014-07-30 11:48:21

标签: c# .net serialization

我有一个基类,其中包含一些属性:

public class BaseClass {  
  public string Name { get; set; }  
  public string Comment { get; set; }  
}  

扩展基类的类如:

public class A : BaseClass {  
  public string AProperty{ get; set; }  
}  

public class B : BaseClass {  
  public string BProperty{ get; set; }  
}  

现在我需要能够将数据从扩展和基类序列化到不同的位置 对于反序列化,我需要能够对其中一个类进行反序列化,并且" merge"与之前被反序列化的基类 基类是我的,所以我可以将它改为needet,但不是扩展类(我样本中的A和B)。
拥有一个适用于XML和JSON(Newtonsoft JSON序列化程序)序列化程序的解决方案会很不错。 谢谢您的想法。

2 个答案:

答案 0 :(得分:1)

我不知道用XML做这个的方法,但使用Newtonsoft JSON.NET:

除非您首先知道最终目标类型,否则无法合并反序列化结果。这可能意味着您必须以某种方式在JSON中包含类型名称,可以通过TypeNameHandling自动或手动包含。

  • 如果您选择使用TypeNameHandling,则可以通过调用Deserialize(JsonReader)创建对象,并让它创建一个正确类型的对象。
  • 如果以其他方式存储类型,则可以使用带有类型的重载来创建对象:Deserialize(JsonReader, Type)

获得正确的对象后,可以通过Populate从第二个片段添加其他属性。


注意:如果你不知道第二个片段之前对象的类型,为什么不将第一个片段保留为JSON并首先解析第二个片段?然后通过Populate添加第一个片段。只要片段没有任何重叠字段,片段反序列化的顺序并不重要。


要执行序列化,您需要使用自定义IContractResolver来过滤字段。例如,像这样的东西将允许过滤到以特定类型声明的所有属性(警告:我没有尝试编译它):

public class DeclaredMembersResolver<T> : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> filtered = new List<JsonProperty>();

        foreach (JsonProperty p in base.CreateProperties(type, memberSerialization))
            if(p.DeclaringType == typeof(T)) 
                filtered.Add(p);

        return filtered;
    }
}

// Example of use:
var ser = JsonSerializer.CreateDefault(new JsonSerializerSettings() {
  ContractResolver = new DeclaredMembersResolver<BaseClass>()
});
ser.Serialize(writer, obj); // Only the base properties of obj will be written

显然,你会扩展上面的内容以反向(排除基类属性)来序列化你的第二个JSON块。

答案 1 :(得分:0)

通过使用JObject和Linq查询反序列化对象的属性并手动执行您想要的操作,可以使用Newtonsoft的JSON库完成您想要做的工作。

可在此处找到更多信息:http://james.newtonking.com/json/help/index.html

作为示例:如果您有一个已经反序列化的baseObject和一个包含数据的字符串:

JObject jObj = JObject.Parse(json);
A aObj = new A();
aObj.Name = baseObject.Name;
aObj.Comment = baseObject.Name;
a.AProperty = (string)jObj[propertyInfo.Name];

如果您不知道对象的其他属性,但可以在运行时访问可以通过反射轻松找到的类型。从上面继续的例子

var t = typeof(A);

PropertyInfo[] pi = t.GetProperties();
foreach (var propertyInfo in pi)
    propertyInfo.SetValue(aObject, (string)jObj["AProperty"]);