web-dev-qa-db-ja.com

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

等...

23
Chris Barry

あなたが求めているのは、jsonで複雑なビジネスオブジェクトをシリアル化する方法ですが、特定のプロパティのみを公開することです。

言い換えれば、すでに学生のリストがありますが、jsonを介して特定のデータのみを送信したいとします。私が間違っていると、この答えはあなたのニーズに合いません。

したがって、タスクの内部プロパティを持つprojectsプロパティを持つ学生のリストがあると仮定すると、これは、新しいクラスのロードを作成する必要なしに行う方法であり、匿名オブジェクトを使用します。

匿名オブジェクトのリストを作成したら、それらを単に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);
34
mattmanser

これは、質問から正確な出力を生成するコードです(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オブジェクトを操作したい場合は、1つのstudentだけで外部配列を作成し、次に別の配列を追加するこの例を見てください。 1:

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

11
mthierba

最後に、これらのモデルを使用しました。

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;

}

現在は完全に機能しています。これを行うより良い方法はありますか?

5
Chris Barry