web-dev-qa-db-fra.com

Comment créer une hiérarchie d'objets pour la sérialisation avec json.net?

J'essaie d'écrire correctement du code pour construire une structure de données à sérialiser en json.

J'utilise json.net.

Je ne veux pas créer un tas de classes pour contenir ces données, car je pensais qu'il devrait y avoir des classes qui le feront déjà dans json.net

J'ai déjà toutes les données dont j'ai besoin dans une série de boucles imbriquées, et maintenant je veux juste les ajouter à une hiérarchie d'objets avant d'exécuter JsonConvert.SerializeObject dessus.

J'ai déjà essayé du code comme celui-ci, mais il ne semble pas fonctionner

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

Le problème est que lorsque j'utilise [i]. Ou ElementAt (i) pour accéder quelque part dans la structure, soit .Add () est manquant ou .ElementAt n'est pas là. Comment puis-je parcourir la structure de données pour que cela soit bien affiché ci-dessous, ou dois-je créer ma propre classe de conteneur pour tout cela?

C'est le format de données que j'essaie de créer.

[
    {
    "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

etc...

23
Chris Barry

Je pense que ce que vous demandez, c'est comment sérialiser des objets métier complexes dans json, mais uniquement exposer certaines propriétés.

En d'autres termes, vous avez déjà une liste d'étudiants, mais vous souhaitez uniquement envoyer des données très spécifiques via json. Si je me trompe, cette réponse ne répondra pas à vos besoins.

Donc, en supposant que vous ayez une liste d'étudiants, avec une propriété de projets qui a une propriété interne de tâches, voici comment je le fais sans avoir à créer des charges de nouvelles classes, j'utilise des objets anonymes.

Une fois que j'ai créé ma liste d'objets anonymes, je les transforme simplement en une chaîne json.

Comme indiqué dans les commentaires, vous n'avez pas besoin d'utiliser json.net, cette fonctionnalité est disponible dans le framework, ajoutez une référence à System.Web.Extensions.dll puis

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

Si vous voulez vraiment utiliser des boucles, vous pouvez le faire pour vous permettre de faire des choses plus compliquées dans la création des projets et des tâches:

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

c'est le code qui génère la sortie exacte de votre question (nécessite un 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();

Je crois que l'utilisation de la syntaxe Json.Net Linq a le grand avantage que le code C # résultant peut être formaté afin qu'il ait presque la même structure que le JSON que vous essayez de générer.

MISE À JOUR

Si vous souhaitez manipuler l'objet Json une fois qu'il a été construit, regardez cet exemple qui construit le tableau externe avec un seul étudiant , puis en ajoute un autre une:

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

L'idée est que vous pouvez appliquer le même principe à n'importe quelle autre partie de la structure de la même manière.

HTH ...

11
mthierba

Au final, j'ai utilisé ces modèles.

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;

}

Cela fonctionne maintenant parfaitement. Y a-t-il une meilleure façon de procéder?

5
Chris Barry