如何用Newtonsoft.Json将单属性对象JSON数组反序列化为字符串集合
解决方案:无需额外类直接反序列化单属性JSON数组为字符串集合
嘿,这个需求我太懂了——谁想为了一个单属性专门建个冗余类啊!下面给你几个实用的方法,不用额外定义ListFieldItem,直接把JSON里的ListField数组反序列成ICollection<string>:
方法1:自定义JsonConverter(推荐,通用且可复用)
写一个通用的转换器,专门处理这种“包含单属性对象的数组”,可以指定要提取的属性名,之后不管是字符串还是其他类型都能复用。
转换器代码:
public class SinglePropertyArrayConverter<T> : JsonConverter<ICollection<T>> { private readonly string _targetPropertyName; // 构造函数传入要提取的属性名(比如这里的"Name") public SinglePropertyArrayConverter(string targetPropertyName) { _targetPropertyName = targetPropertyName; } public override ICollection<T> ReadJson(JsonReader reader, Type objectType, ICollection<T> existingValue, bool hasExistingValue, JsonSerializer serializer) { // 加载JSON数组 var jArray = JArray.Load(reader); // 初始化结果集合(如果已有实例就用现有,否则创建新的) var result = existingValue ?? (ICollection<T>)Activator.CreateInstance(objectType); foreach (var jObject in jArray) { // 提取指定属性的值并转换为目标类型 var value = jObject[_targetPropertyName].ToObject<T>(serializer); result.Add(value); } return result; } // 如果需要序列化回去,也实现WriteJson方法(可选) public override void WriteJson(JsonWriter writer, ICollection<T> value, JsonSerializer serializer) { writer.WriteStartArray(); foreach (var item in value) { writer.WriteStartObject(); writer.WritePropertyName(_targetPropertyName); serializer.Serialize(writer, item); writer.WriteEndObject(); } writer.WriteEndArray(); } }
在目标类中使用:
直接在ListField属性上标记转换器,指定要提取的属性名"Name":
public class ClassName { public string FieldString; public bool FieldBool; public Guid FieldId; // 标记转换器,传入要提取的属性名 [JsonConverter(typeof(SinglePropertyArrayConverter<string>), "Name")] public ICollection<string> ListField; }
之后你原来的反序列化代码完全不用改:
var result = JsonConvert.DeserializeObject<ClassName>(jsonString);
方法2:手动解析(适合临时场景)
如果只是偶尔用一次,不想写转换器,可以先把JSON解析成JObject,手动提取各个字段的值:
// 先解析JSON为JObject var jsonObj = JObject.Parse(jsonString); // 手动映射每个属性 var className = new ClassName { FieldString = jsonObj["FieldString"].ToString(), FieldBool = jsonObj["FieldBool"].ToObject<bool>(), FieldId = jsonObj["FieldId"].ToObject<Guid>(), // 遍历ListField数组,提取每个对象的Name属性 ListField = jsonObj["ListField"] .Select(item => item["Name"].ToString()) .ToList() };
这个方法简单直接,但复用性差,适合临时处理特定JSON的场景。
额外小技巧:全局注册转换器
如果你的项目里有很多这种场景,可以把转换器全局注册到JsonSerializerSettings里,这样不用每个属性都加特性:
var settings = new JsonSerializerSettings(); // 注册针对ICollection<string>且提取"Name"属性的转换器 settings.Converters.Add(new SinglePropertyArrayConverter<string>("Name")); var result = JsonConvert.DeserializeObject<ClassName>(jsonString, settings);
不过这种方式要注意,如果有其他ICollection<string>类型的属性不需要转换,可能会冲突,所以还是属性级别的标记更稳妥。
内容的提问来源于stack exchange,提问作者xzyvvy
相关产品推荐
相关产品推荐

