使用DataContractJsonSerializer反序列化Entity时抛出ArgumentNullException
解决DataContractJsonSerializer反序列化Microsoft.Xrm.Sdk.Entity失败的问题
问题原因
Microsoft.Xrm.Sdk.Entity的Attributes属性是AttributeCollection类型,本质是Dictionary<string, object>的包装类。DataContractJsonSerializer对这类字典类型的序列化/反序列化规则是直接将键值对作为JSON对象的属性,而你提供的JSON中Attributes是包含Key/Value字段的数组,和序列化器期望的格式不匹配,因此抛出空键异常。此外原JSON中的Name字段对应Entity的LogicalName属性,字段名不匹配也会导致映射失败。
解决方案
方案1:修正JSON格式(推荐,符合DataContract规范)
将Attributes从数组改为键值对对象结构,并修正字段名:
{ "Id": "28bdb958-71fd-e711-8129-5065f38be461", "LogicalName": "name", "Attributes": { "key1": "value1", "key2": "value2" } }
使用原代码即可正常反序列化(建议替换ASCII为UTF8避免编码问题):
using System.IO; using System.Runtime.Serialization.Json; using System.Text; using Microsoft.Xrm.Sdk; var serializer = new DataContractJsonSerializer(typeof(Entity)); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); var entity = serializer.ReadObject(stream) as Entity;
方案2:无法修改JSON时,通过中间类转换
定义与输入JSON结构匹配的中间类,反序列化后手动转换为Entity:
using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Json; using System.Text; using Microsoft.Xrm.Sdk; // 中间类匹配JSON结构 public class EntityDto { public Guid Id { get; set; } public string Name { get; set; } public List<AttributeDto> Attributes { get; set; } } public class AttributeDto { public string Key { get; set; } public object Value { get; set; } } // 反序列化并转换为Entity var dtoSerializer = new DataContractJsonSerializer(typeof(EntityDto)); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); var dto = dtoSerializer.ReadObject(stream) as EntityDto; var entity = new Entity(dto.Name) { Id = dto.Id }; foreach (var attr in dto.Attributes) { entity.Attributes.Add(attr.Key, attr.Value); }
方案3:使用Newtonsoft.Json(更灵活)
引入Newtonsoft.Json NuGet包,通过自定义转换器处理非标准格式:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Microsoft.Xrm.Sdk; public class EntityConverter : JsonConverter<Entity> { public override Entity ReadJson(JsonReader reader, Type objectType, Entity existingValue, bool hasExistingValue, JsonSerializer serializer) { var jo = JObject.Load(reader); var entity = new Entity(jo["Name"].ToString()) { Id = Guid.Parse(jo["Id"].ToString()) }; foreach (var attr in jo["Attributes"].Children<JObject>()) { var key = attr["Key"].ToString(); var value = attr["Value"].ToObject<object>(); entity.Attributes.Add(key, value); } return entity; } public override void WriteJson(JsonWriter writer, Entity value, JsonSerializer serializer) { throw new NotImplementedException(); } } // 反序列化 var entity = JsonConvert.DeserializeObject<Entity>(jsonString, new EntityConverter());
内容的提问来源于stack exchange,提问作者David Liang
相关产品推荐
相关产品推荐

