System.Text.Json
的解決方法:System.Text.Json 序列/反序列化 abstract class
用于檢測(cè)類型的枚舉
public enum ItemTypes
{
Unknow = 0,
Name,
EnName,
Mobile,
然评。熊杨。。
抽象類定義:
[JsonConverter(typeof(RequirementConverter))]
[Newtonsoft.Json.JsonConverter(typeof(RequirementConvertJsonNet))]
public abstract class BaseItem
{
public virtual string ItemName { get; set; }
public bool IsRequired { get; set; }
public abstract ItemTypes Type { get; }
public string Value { get; set; }
}
子類定義:
public class AddressItem : BaseItem
{
public override string ItemName { get; set; } = "地址";
public override ItemTypes Type => ItemTypes.Address;
}
用于檢查類型的臨時(shí)類:
private class TypeDetectItem
{
[JsonProperty("Type")]
public ItemTypes _Type { get; set; }
[JsonIgnore]
public ItemTypes Type => this._Type;
}
ContractResolver 定義:
private class BaseItemContractReslover : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
//因?yàn)?BaseItem 上指定了 Converter,
//如果這里不返回 null 的話, 會(huì)一直循環(huán)執(zhí)行, 導(dǎo)致 stackoverflow 異常.
if (typeof(BaseItem).IsAssignableFrom(objectType) && !objectType.IsAbstract)
return null;
return base.ResolveContractConverter(objectType);
}
}
Converter 定義:
public class RequirementConvertJsonNet : JsonConverter<BaseItem>
{
private static readonly JsonSerializerSettings setting = new JsonSerializerSettings()
{
ContractResolver = new BaseItemContractReslover()
};
public override BaseItem ReadJson(JsonReader reader, Type objectType, BaseItem existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jobj = JObject.ReadFrom(reader);
var detect = jobj.ToObject<TypeDetectItem>();
var json = jobj.ToString();
BaseItem o = detect.Type switch
{
ItemTypes.Name => JsonConvert.DeserializeObject<NameItem>(json, setting),
ItemTypes.Credentials => JsonConvert.DeserializeObject<CredentialsItem>(json, setting),
ItemTypes.Address => JsonConvert.DeserializeObject<AddressItem>(json, setting),
...
...
_ => throw new NotImplementedException(),
};
return o;
}
public override void WriteJson(JsonWriter writer, BaseItem value, JsonSerializer serializer)
{
//這樣寫會(huì)報(bào):Self referencing loop detected with type xxx
//serializer.Serialize(writer, value, value?.GetType() ?? typeof(object));
var json = JsonConvert.SerializeObject(value, value?.GetType() ?? typeof(object), setting);
//writer.WriteRaw 會(huì)缺少逗號(hào), writer.WriteValue 會(huì)把引號(hào)加上反斜杠值纱。
writer.WriteRawValue(json);
}