自定义JsonConverter仅反序列化Actions属性失败,求解决方案
问题描述
我正在处理如下复杂JSON结构的反序列化,其中events下的id代表对应事件:
"events": [ { "id": 1, "actions": [ { "id": 8, "values": { "obj_id":160, "url": "https://www.myurl.com/" } }, { "id":15, "values":{ "obj_id":182, "scale":200 } } ] } ]
我定义了抽象类ActionBase及多个派生类,不同的action id对应不同的values类型,相关C#类结构如下:
public class Events { public int id; public ActionsHolder[] actions; } [JsonConverter(typeof(BaseConverter))] public class ActionsHolder { public int id { get; set; } = -1; public ActionBase values { get; set; } } public abstract class ActionBase : ActionsHolder { public int obj_id { get; set; } } public class OpenURLAction : ActionBase { //Action id 8 = Open URL public string url { get; set; } } public class ScaleAction : ActionBase { //Action id 15 = Scale public float scale { get; set; } = 1; }
同时编写了自定义JsonConverter代码:
public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver { protected override JsonConverter ResolveContractConverter(Type objectType) { if (typeof(ActionsHolder).IsAssignableFrom(objectType) && !objectType.IsAbstract) { return null; } return base.ResolveContractConverter(objectType); } } public class BaseConverter : JsonConverter { static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() , TypeNameHandling = TypeNameHandling.All }; public override bool CanConvert(Type objectType) { return (objectType == typeof(ActionsHolder)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject joAction = JObject.Load(reader); JObject joValues = (JObject)joAction["values"]; switch (joAction["id"].Value<int>()) { case 8: return new ActionsHolder { id = joAction["id"].Value<int>(), values = JsonConvert.DeserializeObject<OpenURLAction>(joValues.ToString(), SpecifiedSubclassConversion) }; case 15: return new ActionsHolder { id = joAction["id"].Value<int>(), values = JsonConvert.DeserializeObject<ScaleAction>(joValues.ToString(), SpecifiedSubclassConversion) }; default: return null; } throw new NotImplementedException(); } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
但目前该实现无法正常工作,我希望让自定义转换器仅处理actions属性,其余属性使用默认转换器,请问该如何修正?
修正方案
1. 修复ActionBase的继承关系(核心修复)
原代码中ActionBase继承自ActionsHolder属于逻辑错误,会导致类型嵌套递归,直接修改ActionBase为独立抽象类:
public abstract class ActionBase { public int obj_id { get; set; } }
2. 移除ActionsHolder类上的全局转换器标记
把ActionsHolder类上的[JsonConverter(typeof(BaseConverter))]特性删除,避免全局强制使用该转换器:
public class ActionsHolder { public int id { get; set; } = -1; public ActionBase values { get; set; } }
3. 给Events的actions属性单独指定转换器
在Events类的actions字段上添加特性,仅让该属性的元素使用自定义转换器:
public class Events { public int id; [JsonProperty(ItemConverterType = typeof(BaseConverter))] public ActionsHolder[] actions; }
4. 简化自定义转换器逻辑
移除多余的TypeNameHandling和自定义契约解析器,直接通过action id匹配派生类型:
public class BaseConverter : JsonConverter<ActionsHolder> { public override ActionsHolder ReadJson(JsonReader reader, Type objectType, ActionsHolder existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject joAction = JObject.Load(reader); var holder = new ActionsHolder(); // 用默认序列化逻辑处理id属性 serializer.Populate(joAction.CreateReader(), holder); int actionId = joAction["id"].Value<int>(); JObject joValues = (JObject)joAction["values"]; switch (actionId) { case 8: holder.values = joValues.ToObject<OpenURLAction>(serializer); break; case 15: holder.values = joValues.ToObject<ScaleAction>(serializer); break; default: throw new NotSupportedException($"不支持的Action ID: {actionId}"); } return holder; } public override void WriteJson(JsonWriter writer, ActionsHolder value, JsonSerializer serializer) { // 若不需要序列化可抛出异常,或按需实现序列化逻辑 throw new NotImplementedException(); } }
5. 正常执行反序列化
现在直接用默认配置反序列化即可,自定义转换器只会作用于actions数组的元素:
var eventsList = JsonConvert.DeserializeObject<List<Events>>(yourJsonString);
内容的提问来源于stack exchange,提问作者user22792033
相关产品推荐
相关产品推荐

