Как создать иерархию объектов для сериализации с помощью 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

и т.д...

Ответ 1

Я думаю, что вы спрашиваете, как сериализовать сложные бизнес-объекты в json, но выставлять только определенные свойства.

Другими словами, у вас уже есть список студентов, но вы хотите отправлять очень специфичные данные через json. Если я ошибаюсь, этот ответ не будет соответствовать вашим потребностям.

Итак, предполагая, что у вас есть список студентов, с свойством проектов, которое имеет внутреннее свойство задач, так я это делаю, не создавая множество новых классов, я использую анонимные объекты.

Как только я создал свой список анонимных объектов, я просто превращу их в строку json.

Как указано в комментариях, вам не нужно использовать json.net, эта функциональность доступна в фреймворке, добавьте ссылку на System.Web.Extensions.dll, затем

с использованием System.Web.Script.Serialization;

var jsonStudents = new List<object>();

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<object>();

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<object>()
    };

    foreach (var project in student.Projects)
    {
        var tempProject = new {
            project.Id,
            project.Name,
            Tasks = new List<object>()
        };

        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);

Ответ 2

это код, который генерирует точный результат из вашего вопроса (требуется 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 имеет большое преимущество в том, что полученный С# -код может быть отформатирован так, что он почти имеет ту же структуру, что и 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, i.e. "student1"
    .AddAfterSelf(student2);     // adds this which hence becomes the new last one

Идея состоит в том, что вы можете применить тот же самый принцип к любой другой части структуры таким же образом.

НТН...

Ответ 3

В конце я использовал эти Модели.

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

}

Теперь он работает отлично. Есть ли лучший способ сделать это?