如何使用json.net构建序列化的对象层次结构?

我正在尝试正确编写代码来构建数据结构以序列化为json。

我正在使用json.net。

我不想创建一堆类来保存这些数据,因为我认为应该有一些类已经在json.net中执行此操作

我已经在一系列嵌套循环中获得了所需的所有数据,现在我只想在它上运行JsonConvert.SerializeObject之前将它们添加到对象层次结构中。

我已经尝试过这样的代码,但似乎没有用

JArray container = new JArray(); container.Add(new JObject(new JProperty("name", "Client1"), new JProperty("projects", new JArray()))); container[0].AddAfterSelf(new JObject(new JProperty("projects", new JArray()))); container[1].AddAfterSelf(new JObject(new JProperty("projects", "Project2"))); container[1].AddAfterSelf(new JObject(new JProperty("projects", "Project3"))); container.Add(new JProperty("name", "Client2")); var test = JsonConvert.SerializeObject(container); 

问题是当我使用[i]时。 或者ElementAt(i)访问结构中的某个地方,或者缺少.Add()或者没有.ElementAt。 如何逐步完成数据结构以使下面的输出良好,或者我是否必须为所有这些创建自己的容器类?

这是我想要的数据格式。

 [ { "name": "student1", "projects": [ { "name": "Project1", "tasks": [ { "name": "task1", "id": 2 } ], "id": 6 } ] }, { "name": "Student2", "projects": [ { "name": "Project1", "tasks": [ { "name": "Task2", "id": 1 }, { "name": "Task3", "id": 3 }, { "name": "Task4", "id": 4 } ], "id": 2 

等等…

我想你要问的是如何在json中序列化复杂的业务对象,但只暴露某些属性。

换句话说,您已经有一个学生列表,但您只想通过json发送非常具体的数据。 如果我错了,这个答案将不适合你的需要。

因此,假设您有一个学生列表,其中一个项目属性具有任务的内部属性,这就是我如何在不创建新类的情况下执行的操作,而是使用匿名对象。

一旦我创建了匿名对象列表,我只需将它们变成一个json字符串。

正如评论中指出的那样你不需要使用json.net,这个function在框架中可用,添加对System.Web.Extensions.dll的引用然后

使用System.Web.Script.Serialization;

 var jsonStudents = new List(); foreach (var student in students) { jsonStudents.Add(new { student.Id, //anonymous properties automatically pick up the name of the property you pass them, this will be called Id FullName = student.FirstName + " " + student.LastName, //if you want to name a property yourself use this notation Projects = student.Projects.Select(p => new //this will be an enumerable of nested anonymous objects, we're partially selecting project properties { p.Id, p.Name, Tasks = p.Tasks.Select(t => new //nesting another level { t.Id, t.Name }) }) }); } var serializer = new JavaScriptSerializer(); var jsonString = serializer.Serialize(jsonStudents); 

如果你真的想使用循环,你可以这样做,让你在创建项目和任务时做更复杂的事情:

 var jsonStudents = new List(); foreach (var student in students) { var tempStudent = new { student.Id, //anonymous properties automatically pick up the name of the property you pass them, this will be called Id FullName = student.FirstName + " " + student.LastName, //if you want to name a property yourself use this notation Projects = new List() }; foreach (var project in student.Projects) { var tempProject = new { project.Id, project.Name, Tasks = new List() }; foreach (var task in project.Tasks) { tempProject.Tasks.Add(new { task.Id, task.Name }); } tempStudent.Projects.Add(tempProject); } jsonStudents.Add(tempStudent); } var serializer = new JavaScriptSerializer(); var jsonString = serializer.Serialize(jsonStudents); 

这是从您的问题生成确切输出的代码(需要using Newtonsoft.Json.Linq; ):

 var json = new JArray( new JObject( new JProperty("name", "student1"), new JProperty("projects", new JArray( new JObject( new JProperty("name", "Project1"), new JProperty("tasks", new JArray( new JObject( new JProperty("name", "task1"), new JProperty("id", 2) ) ) ), new JProperty("id", 6) ) ) ) ), new JObject( new JProperty("name", "student2"), new JProperty("projects", new JArray( new JObject( new JProperty("name", "Project1"), new JProperty("tasks", new JArray( new JObject( new JProperty("name", "task2"), new JProperty("id", 1) ), new JObject( new JProperty("name", "task3"), new JProperty("id", 3) ), new JObject( new JProperty("name", "task4"), new JProperty("id", 4) ) ) ), new JProperty("id", 2) ) ) ) ) ); var jsonString = json.ToString(); 

我相信使用Json.Net Linq语法具有很大的优势,可以对生成的C#代码进行格式化,使其几乎与您尝试生成的JSON具有相同的结构。

UPDATE

如果你想在构建Json对象之后对其进行操作,请查看这个仅使用一个学生构建外部数组的示例,然后添加另一个:

 // create an isolated Student instance: var student2 = new JObject( new JProperty("name", "student2"), new JProperty("projects", new JArray( new JObject( new JProperty("name", "Project1"), new JProperty("tasks", new JArray( new JObject( new JProperty("name", "task2"), new JProperty("id", 1) ), new JObject( new JProperty("name", "task3"), new JProperty("id", 3) ), new JObject( new JProperty("name", "task4"), new JProperty("id", 4) ) ) ), new JProperty("id", 2) ) ) ) ); var json = new JArray( new JObject( new JProperty("name", "student1"), new JProperty("projects", new JArray( new JObject( new JProperty("name", "Project1"), new JProperty("tasks", new JArray( new JObject( new JProperty("name", "task1"), new JProperty("id", 2) ) ) ), new JProperty("id", 6) ) ) ) ) ); // now, add the student2 instance to the array: json // which is an JArray .Last // gets the last Array item, ie "student1" .AddAfterSelf(student2); // adds this which hence becomes the new last one 

我们的想法是,您可以以相同的方式将相同的原理应用于结构的任何其他部分。

HTH …

最后我使用了这些模型。

 public class JStudent { public List projects = new List(); public string name; public string id; } public class JProject { public List tasks = new List(); public string name; public string id; } public class JTask { public string name; public string id; } 

它现在工作得很好。 有没有更好的方法来做到这一点?