如何使用JSON.NET将指定JSON反序列化为List<Person>集合
解决方案
1. 定义实体类
先根据JSON结构定义对应的数据类:
// 科目类,根据实际JSON的subjects字段调整属性 public class Subject { public string Name { get; set; } public int? Score { get; set; } // 支持学生带分数、老师仅科目名的场景 } // 最终的人员类,Id存储原JSON的键(如student 1) public class Person { public string Id { get; set; } public string Name { get; set; } public Subject[] Subjects { get; set; } } // 包含人员集合的自定义类 public class MyClass { public List<Person> People { get; set; } }
2. 反序列化实现方案
方法一:字典中转映射(简单直观)
由于原JSON是键值对结构(键为student 1这类标识,值为人员数据),可以先反序列化为字典,再手动映射为List<Person>:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; // 示例JSON字符串 string json = @" { ""student 1"": { ""name"": ""Alice"", ""subjects"": { ""Math"": 95, ""English"": 88 } }, ""student 2"": { ""name"": ""Bob"", ""subjects"": { ""Physics"": 90, ""Chemistry"": 85 } }, ""teacher 1"": { ""name"": ""Mr. Smith"", ""subjects"": [""Math"", ""Physics""] } }"; // 1. 反序列化为字典,键是原JSON的标识,值为JObject var personDict = JsonConvert.DeserializeObject<Dictionary<string, JObject>>(json); // 2. 映射为List<Person> var people = new List<Person>(); foreach (var kvp in personDict) { var person = new Person { Id = kvp.Key, Name = kvp.Value["name"].ToString() }; // 处理subjects:兼容对象(科目:分数)和数组(纯科目名)两种格式 var subjectsToken = kvp.Value["subjects"]; if (subjectsToken.Type == JTokenType.Object) { person.Subjects = subjectsToken .Children<JProperty>() .Select(p => new Subject { Name = p.Name, Score = int.Parse(p.Value.ToString()) }) .ToArray(); } else if (subjectsToken.Type == JTokenType.Array) { person.Subjects = subjectsToken .Select(s => new Subject { Name = s.ToString() }) .ToArray(); } people.Add(person); } // 赋值给MyClass var myClass = new MyClass { People = people };
方法二:自定义JsonConverter(一步到位)
如果想直接反序列化为MyClass,可以编写自定义转换器:
public class MyClassConverter : JsonConverter<MyClass> { public override MyClass ReadJson(JsonReader reader, Type objectType, MyClass existingValue, bool hasExistingValue, JsonSerializer serializer) { var personDict = serializer.Deserialize<Dictionary<string, JObject>>(reader); var people = new List<Person>(); foreach (var kvp in personDict) { var person = new Person { Id = kvp.Key, Name = kvp.Value["name"].ToString() }; // 同方法一处理subjects var subjectsToken = kvp.Value["subjects"]; if (subjectsToken.Type == JTokenType.Object) { person.Subjects = subjectsToken .Children<JProperty>() .Select(p => new Subject { Name = p.Name, Score = int.Parse(p.Value.ToString()) }) .ToArray(); } else if (subjectsToken.Type == JTokenType.Array) { person.Subjects = subjectsToken .Select(s => new Subject { Name = s.ToString() }) .ToArray(); } people.Add(person); } return new MyClass { People = people }; } public override void WriteJson(JsonWriter writer, MyClass value, JsonSerializer serializer) { // 如需序列化回JSON,可自行实现,此处省略 throw new NotImplementedException(); } }
使用转换器:
var myClass = JsonConvert.DeserializeObject<MyClass>(json, new MyClassConverter());
关键说明
- 核心逻辑是用字典接收原JSON的键值对,将字典的Key作为Person的Id字段
- subjects的处理逻辑需匹配实际JSON结构,若你的subjects本身就是标准数组(如
[{"name":"Math", "score":95}]),可直接用serializer.Deserialize<Subject[]>(subjectsToken)转换
内容的提问来源于stack exchange,提问作者Paul Lee
相关产品推荐
相关产品推荐

