可能不想使用TypeNameHandling(因爲我們想要更緊湊的json或者希望使用除「$ type」之外的類型變量的特定名稱)。與此同時,customerCreationConverter approach不會工作,如果有人想將基類反序列化爲多個派生類中的任何一個,而不知道預先使用哪一個類。
另一種方法是在基類中使用int或其他類型並定義JsonConverter。
[JsonConverter(typeof(BaseConverter))]
abstract class Base
{
public int ObjType { get; set; }
public int Id { get; set; }
}
class DerivedType1 : Base
{
public string Foo { get; set; }
}
class DerivedType2 : Base
{
public string Bar { get; set; }
}
基類的JsonConverter可以根據其類型反序列化對象。複雜的是,爲了避免堆棧溢出(JsonConverter重複調用它自己),必須在此反序列化過程中使用自定義合約解析器。
public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(Base).IsAssignableFrom(objectType) && !objectType.IsAbstract)
return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
return base.ResolveContractConverter(objectType);
}
}
public class BaseConverter : JsonConverter
{
static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() };
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Base));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
switch (jo["ObjType"].Value<int>())
{
case 1:
return JsonConvert.DeserializeObject<DerivedType1>(jo.ToString(), SpecifiedSubclassConversion);
case 2:
return JsonConvert.DeserializeObject<DerivedType2>(jo.ToString(), SpecifiedSubclassConversion);
default:
throw new Exception();
}
throw new NotImplementedException();
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // won't be called because CanWrite returns false
}
}
就是這樣。現在你可以使用序列化/反序列化任何派生類。你也可以用在其他類的基類和序列化/反序列化那些沒有任何額外的工作:
class Holder
{
public List<Base> Objects { get; set; }
}
string json = @"
[
{
""Objects"" :
[
{ ""ObjType"": 1, ""Id"" : 1, ""Foo"" : ""One"" },
{ ""ObjType"": 1, ""Id"" : 2, ""Foo"" : ""Two"" },
]
},
{
""Objects"" :
[
{ ""ObjType"": 2, ""Id"" : 3, ""Bar"" : ""Three"" },
{ ""ObjType"": 2, ""Id"" : 4, ""Bar"" : ""Four"" },
]
},
]";
List<Holder> list = JsonConvert.DeserializeObject<List<Holder>>(json);
string serializedAgain = JsonConvert.SerializeObject(list);
Debug.WriteLine(serializedAgain);
反序列化,你需要創建對象實例,但你不能創建抽象類 – Grundy
的情況下,我希望它創建一個具體的類的實例,對不起,如果不清楚 – aochagavia
你能提供多一點的代碼嗎? – Grundy