.NET中JsonConvert兼容Survey数据单对象/数组反序列化的解决
解决API返回单条/多条/零条Survey数据的JSON反序列化兼容问题
问题根源是API返回的Response节点类型不统一:多条数据时为数组,单条时为单个对象,零条时可能无节点或为null,导致Newtonsoft.Json无法直接适配数组类型的属性。以下是最可靠的解决方案:
方案1:自定义JsonConverter统一处理对象/数组转换
步骤1:实现SingleOrArrayConverter转换器
这个转换器会自动将单个对象包装为数组,数组直接保留,空值/无节点返回空数组:
public class SingleOrArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(T[]) || objectType == typeof(List<T>); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var tokenType = reader.TokenType; switch (tokenType) { case JsonToken.StartArray: return serializer.Deserialize<T[]>(reader); case JsonToken.StartObject: var singleItem = serializer.Deserialize<T>(reader); return new T[] { singleItem }; case JsonToken.Null: case JsonToken.Undefined: return Array.Empty<T>(); default: throw new JsonSerializationException($"无法处理的Token类型:{tokenType}"); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 如需序列化时自动适配(单条写对象,多条写数组),可保留此方法;仅反序列化的话也可留空 var array = value as T[]; if (array?.Length == 1) { serializer.Serialize(writer, array[0]); } else { serializer.Serialize(writer, value); } } }
步骤2:修改实体类并添加转换器特性
同时修正JSON键名匹配问题(原JSON中的"?xml"和"@version"需要用JsonProperty特性映射):
public class SurveyJsonModel { public class Rootobject { [JsonProperty("?xml")] public Xml Xml { get; set; } public Responses Responses { get; set; } } public class Xml { [JsonProperty("@version")] public string Version { get; set; } } public class Responses { [JsonConverter(typeof(SingleOrArrayConverter<Response>))] public Response[] Response { get; set; } } public class Response { public string startDate { get; set; } public string endDate { get; set; } public string status { get; set; } public string ipAddress { get; set; } } }
步骤3:正常使用反序列化代码
无需修改原有反序列化逻辑,直接调用即可兼容三种场景:
var surveyData = JsonConvert.DeserializeObject<SurveyJsonModel.Rootobject>(json);
兼容场景说明
- 多条数据:
Response为数组时,转换器直接反序列化为数组 - 单条数据:
Response为单个对象时,转换器自动包装为单元素数组 - 零条数据:
Response节点不存在、为null或空数组时,返回Array.Empty<Response>(),避免空引用异常
内容的提问来源于stack exchange,提问作者user13714356
相关产品推荐
相关产品推荐

