[英]Serializing json object with its private properties deeply
我想序列化屬於不可修改庫 class 的特定私有字段,我該怎么做?
要序列化私有字段,我知道我可以修改設置以序列化所有私有字段,但我不想序列化所有字段。 只是特定的字段。
另外為了序列化私有字段,我知道可以在私有字段上寫入 JsonProperty 或 DataMember 屬性。 但我不能這樣做,因為我不能修改庫類。 即使我可以修改它,該庫在修改庫 class 后依賴於外部庫(例如它依賴於 Newtonsoft.Json.dll 如果使用了 JsonProperty 屬性)。
所以我嘗試創建一個自定義屬性來解決它。
// The class to serialize
public class FeatureRepository
{
// Serialize all private properties that belongs to this object.
public IDGenerator FeatureIDs;
// Do not serialize any private property that belongs to this object!
public IDGenerator oldFeatureIDs;
}
// Unmodifiable library class. Also it must be independent from any external libraries.
// There are some private fields but they do not seem.
public class IDGenerator
{
public IDGenerator();
public uint GenerateID();
public bool IsIDUsed(uint id);
public void ReleaseID(uint id);
public void UseID(uint id);
}
// Custom contract resolver
public class MyContractResolver : DefaultContractResolver
{
// Target properties
private List<SerializableJson> serializableJsons = new List<SerializableJson>();
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
JsonObjectContract contract = base.CreateObjectContract(objectType);
// Detect SerializableJsonAttribute and store the property info
foreach (JsonProperty property in contract.Properties)
{
IList<Attribute> attributes = property.AttributeProvider.GetAttributes(typeof(SerializableJsonAttribute), false);
foreach (SerializableJsonAttribute temp in attributes)
{
if (temp != null)
{
SerializableJson serializableJson = new SerializableJson()
{
PropertyType = property.PropertyType,
PropertyName = property.PropertyName
};
serializableJsons.Add(serializableJson);
}
}
}
return contract;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
List<MemberInfo> members = base.GetSerializableMembers(objectType);
// It can compare just the type, can not compare the property name here.
SerializableJson serializableJson = serializableJsons.Where(temp => temp.PropertyType == objectType).FirstOrDefault();
// If the type is target type, add also private fields.
if (serializableJson != null)
{
IEnumerable<MemberInfo> nonPublicMembers = GetFieldsAndProperties(objectType, BindingFlags.NonPublic)
.Where(m => m is PropertyInfo p ? !IsIndexedProperty(p) : true);
foreach (MemberInfo member in nonPublicMembers)
members.Add(member);
}
return members;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = false)]
public class SerializableJsonAttribute : Attribute
{
}
public class SerializableJson
{
public Type PropertyType { get; set; }
public string PropertyName { get; set; }
}
// Finally use the custom attribute SerializableJson
// Both of them will serialized with theirs private fields.
public class FeatureRepository
{
[SerializableJson]
public IDGenerator FeatureIDs; // I want to serialize all private properties that belongs to this object.
public IDGenerator oldFeatureIDs; // I do not want to serialize any private property that belongs to this object!
}
我該如何解決? 或者有什么不同的方法可以解決這個問題而不是我嘗試過的方法?
塊引用
編輯讓我一步一步解釋問題:首先,FeatureRepository被序列化,SerializableJsonAttribute被搜索所有屬性。 它在 FeatureIDs 屬性上找到屬性,但在 oldFeatureIDs 上。 因此它存儲屬性類型“IDGenerator”和屬性名稱“FeatureIDs”。 其次,它開始序列化 IDGenerator。 在序列化 IDGenerator 時,您無法知道序列化是針對“FeatureIDs”屬性或“oldFeatureIDs”屬性完成的。 如果您知道,您可以為“FeatureIDs”屬性添加私有字段。
https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm顯示您可以按屬性名稱過濾。
也可以使用 IContractResolver 設置 ShouldSerialize。 如果您不想在 class 上放置 ShouldSerialize 方法,或者您沒有聲明 class 並且無法聲明,則使用 IContractResolver 有條件地序列化屬性很有用。
該頁面包含完整的實現:
(...)
if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager")
{
property.ShouldSerialize = ...
(...)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.