簡短的回答是肯定的,那將是適當的地方開始。這裏是我結束了(現在):
public class MyContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
foreach (var pi in type.GetProperties().Where(pi => typeof (Entity).IsAssignableFrom(pi.DeclaringType) && Attribute.IsDefined((MemberInfo) pi, typeof(IdNameMemberAttribute))))
{
properties.Add(CreateReferenceProperty(pi, Reflect.GetProperty<Entity>(e => e.Id)));
properties.Add(CreateReferenceProperty(pi, Reflect.GetProperty<Entity>(e => e.Name)));
}
return properties;
}
private JsonProperty CreateReferenceProperty(PropertyInfo reference, PropertyInfo referenceMember)
{
var jsonProperty = base.CreateProperty(reference, MemberSerialization.OptOut);
jsonProperty.PropertyName += referenceMember.Name;
jsonProperty.ValueProvider = new ReferencedValueProvider(reference, referenceMember);
jsonProperty.Writable = false;
return jsonProperty;
}
}
IdNameMemberAttribute
只是我用來註釋我想序列,其參考性空的屬性。重要的是,我不會用任何Json.NET將會識別的東西來標註它,並用它來生成一個JsonProperty。這樣我就不會從我的CreateProperties中得到重複的JsonProperty。
或者我可以派生自DataMemberAttribute並查找,修改和克隆JsonProperty來表示我的Id
和Name
。
對於我的asp.net web api,然後將此MyContractResolver設置爲JsonFormatter.SerializerSettings的ContractResolver。
因此,我固定了序列化。對於反序列化,我有一個自定義的ChangeSet對象,用於存儲PropertyInfo和對象。在反序列化過程中,我確保保留Ids,稍後解決數據存儲中的問題,在我的情況下使用自定義ActionFilter訪問數據存儲會話。
這裏是我的序列化的本質:
var jsonSource = streamReader.ReadToEnd();
var deserializedObject = JsonConvert.DeserializeObject(jsonSource, type, SerializerSettings);
var changeSet = deserializedObject as PropertyChangeSet;
if (changeSet != null)
{
var jsonChange = JObject.Parse(jsonSource)["Change"].Cast<JProperty>().ToArray();
IDictionary<string, int> references = jsonChange.Where(IsReferenceId).ToDictionary(t => t.Name.Substring(0, t.Name.Length - 2), t => t.Value.ToObject<int>());
changeSet.References = references;
var properties = jsonChange.Where(jp => !IsReferenceId(jp)).Select(t => t.Name).ToList();
changeSet.Primitives = properties;
}
而且急,我所有的清潔實體和動態序列化的血淋淋的細節被封裝,遺憾的是在兩個地方,但它不能,因爲我得到幫助不想從串行器訪問我的數據源。