Как построить иерархию объектов для сериализации с json.net? - PullRequest
23 голосов
/ 12 мая 2011

Я пытаюсь правильно написать код для построения структуры данных для сериализации в 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

и т.д ...

Ответы [ 3 ]

34 голосов
/ 17 мая 2011

Я думаю, что вы спрашиваете, как сериализовать сложные бизнес-объекты в 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);
11 голосов
/ 15 мая 2011

это код, который генерирует точный вывод из вашего вопроса (требуется 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, который вы пытаетесь сгенерировать.

ОБНОВЛЕНИЕ

Если вы хотите манипулировать объектом Json после егобыл построен, посмотрите на этот пример, который строит внешний массив только с одним student , а затем добавляет еще один:

// 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

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

HTH ...

4 голосов
/ 16 мая 2011

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

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;

}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...