第三方JSON动态反序列化:如何根据对象类型匹配对应模型类?
问题解决方案
核心问题分析
你当前的JsonConverter直接标注在Properties字段上,导致只能访问到properties节点的JSON内容,无法获取外层的objectType字段值,因此无法判断应该将其反序列化为哪个目标模型(ContactPropertiesModel/DealPropertiesModel/PetPropertiesModel)。
解决方案步骤
1. 调整主模型的Converter位置
将JsonConverter从Properties字段移到WorkflowWebhookModel类上,这样就能在Converter中读取整个JSON对象,先获取objectType再处理properties。
修正后的主模型代码:
[DataContract] [JsonConverter(typeof(WorkflowWebhookModelConverter))] // 类级别的Converter public class WorkflowWebhookModel { [DataMember(Name = "objectType")] public string ObjectType { get; set; } [DataMember(Name = "objectTypeId")] public string ObjectTypeId { get; set; } [DataMember(Name = "objectId")] // 修正原代码中字段名的笔误(原incobjectIdeption_date) public long? ObjectId { get; set; } [DataMember(Name = "properties")] public dynamic Properties { get; set; } // 移除字段上的Converter }
2. 实现类级别的自定义Converter
编写WorkflowWebhookModelConverter,先读取基础字段拿到objectType,再根据类型反序列化对应的Properties模型:
public class WorkflowWebhookModelConverter : JsonConverter<WorkflowWebhookModel> { public override WorkflowWebhookModel ReadJson(JsonReader reader, Type objectType, WorkflowWebhookModel existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var jObject = JObject.Load(reader); var model = new WorkflowWebhookModel(); // 反序列化基础字段 model.ObjectType = jObject["objectType"]?.ToString(); model.ObjectTypeId = jObject["objectTypeId"]?.ToString(); model.ObjectId = jObject["objectId"]?.Value<long?>(); // 根据objectType匹配对应的Properties模型 var propertiesToken = jObject["properties"]; if (propertiesToken != null && propertiesToken.Type == JTokenType.Object) { switch (model.ObjectType?.Trim().ToLower()) { case "contact": model.Properties = propertiesToken.ToObject<ContactPropertiesModel>(serializer); break; case "deal": model.Properties = propertiesToken.ToObject<DealPropertiesModel>(serializer); break; case "pet": model.Properties = propertiesToken.ToObject<PetPropertiesModel>(serializer); break; default: // 处理未知类型:可选返回原始JObject或抛出异常 model.Properties = propertiesToken.ToObject<JObject>(serializer); break; } } return model; } public override void WriteJson(JsonWriter writer, WorkflowWebhookModel value, JsonSerializer serializer) { // 序列化逻辑(如果需要):根据Properties的实际类型生成对应JSON var jObject = new JObject(); jObject.Add("objectType", value.ObjectType); jObject.Add("objectTypeId", value.ObjectTypeId); jObject.Add("objectId", value.ObjectId); if (value.Properties != null) { var propertiesToken = JToken.FromObject(value.Properties, serializer); jObject.Add("properties", propertiesToken); } jObject.WriteTo(writer); } }
3. 确保目标模型字段映射正确
三个目标模型类需确保字段与JSON结构匹配,通过DataMember特性绑定JSON键名:
[DataContract] public class PetPropertiesModel { [DataMember(Name = "petName")] public string PetName { get; set; } [DataMember(Name = "petAge")] public int? PetAge { get; set; } // 其他专属属性 } [DataContract] public class ContactPropertiesModel { [DataMember(Name = "contactName")] public string ContactName { get; set; } [DataMember(Name = "contactEmail")] public string ContactEmail { get; set; } // 其他专属属性 } [DataContract] public class DealPropertiesModel { [DataMember(Name = "dealAmount")] public decimal? DealAmount { get; set; } [DataMember(Name = "dealStage")] public string DealStage { get; set; } // 其他专属属性 }
额外说明
- 原代码中
token.ToObject<PetPropertiesModel>()返回null,大概率是因为JSON结构与PetPropertiesModel字段不匹配,需检查字段名映射或JSON格式是否正确。 - 若需处理更多类型,只需在
switch分支中添加对应类型的判断即可。
内容的提问来源于stack exchange,提问作者Kerieks
相关产品推荐
相关产品推荐

