4

ファイルの名前とそのファイルが利用可能なフォルダーを含む C# 辞書オブジェクトがあります。データを階層ツリーに変換したい。以下はデータです。ツリー構造の JSON に変換するにはどうすればよいですか。

この例を調べましたが、目的の出力を得ることができません。

+-----------------------------------------------+|
|  Name             | Path 
|------------------------------------------------|
| Kitchen supplies  |  Shopping / Housewares     |
| Groceries         |  Shopping / Housewares     |
| Cleaning supplies |  Shopping / Housewares     |
| Office supplies   |  Shopping / Housewares     |
| Retile kitchen    |  Shopping / Remodeling     |
| Ceiling           |  Shopping / Paint bedroom  |
| Walls             |  Shopping / Paint bedroom  |
| Misc              |  null                      |
| Other             |  Shopping                  | 
+-----------------------------------------------+|

次のような出力を生成する必要があります。

   {"text":".","children": [
    {
        Name:' Shopping',
        children:[{
            Name:'Housewares',
            children:[{
                Name:'Kitchen supplies',
                leaf:true,
            },{
                Name:'Groceries',
                leaf:true,
            },{
                Name:'Cleaning supplies',
                leaf:true,
            },{
                Name: 'Office supplies',
                leaf: true,
            }]
        }, {
            Name:'Remodeling',
            children:[{
                Name:'Retile kitchen',
                leaf:true,
            },{
                Name:'Paint bedroom',
                children: [{
                    Name: 'Ceiling',
                    leaf: true
                }, {
                    Name: 'Walls',
                    iconCls: 'Name',
                }]
            },
            {
                Name: 'Other',
                leaf: true
            }]
        }]
    },
    {
        Name: 'Misc',
        leaf: true
    }
]}
4

1 に答える 1

6

リンク先の例のように、2 つの主要なタスクがあります。まず、辞書からデータを階層形式に取得する必要があります。これが完了したら、JSON へのシリアル化について心配することができます。

まずNode、階層を表すクラスが必要です。

class Node
{
    public Node()
    {
        Children = new List<Node>();
    }

    public string Name { get; set; }
    public List<Node> Children { get; set; }
}

それができたら、ディクショナリを調べてツリーを構築できます。(注: 目的の JSON では、Paint bedroomandOtherを の下位に表示Remodelingしますが、辞書データの例では、 の下位に表示しShoppingます。この場合、JSON は正しいと想定しているため、以下に示すように、それに応じて辞書データを変更しました。)

Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("Kitchen supplies", "Shopping / Housewares");
dict.Add("Groceries", "Shopping / Housewares");
dict.Add("Cleaning supplies", "Shopping / Housewares");
dict.Add("Office supplies", "Shopping / Housewares");
dict.Add("Retile kitchen", "Shopping / Remodeling");
dict.Add("Ceiling", "Shopping / Remodeling / Paint bedroom");
dict.Add("Walls", "Shopping / Remodeling / Paint bedroom");
dict.Add("Misc", null);
dict.Add("Other", "Shopping / Remodeling");

Node root = new Node();
foreach (KeyValuePair<string, string> kvp in dict)
{
    Node parent = root;
    if (!string.IsNullOrEmpty(kvp.Value))
    {
        Node child = null;
        foreach (string part in kvp.Value.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries))
        {
            string name = part.Trim();
            child = parent.Children.Find(n => n.Name == name);
            if (child == null)
            {
                child = new Node { Name = name };
                parent.Children.Add(child);
            }
            parent = child;
        }
    }
    parent.Children.Add(new Node { Name = kvp.Key });
}

ツリーができたので、それをシリアル化できます。ただし、JSON ではリーフ ノードが非リーフ ノードとは異なる方法でレンダリングされるため、特別な処理が必要です。リーフ ノードにはプロパティがあり、leafプロパティはありませんchildrenが、非リーフ ノードの場合はその逆です。このロジックを処理するには、カスタムが必要JsonConverterです。(明確にするために、ここではJson.Netを使用しています。あなたの質問では、特定の JSON シリアライザーについて言及していませんでした。)

class NodeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Node));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Node node = (Node)value;
        JObject jo = new JObject();
        jo.Add("name", node.Name);
        if (node.Children.Count == 0)
        {
            jo.Add("leaf", true);
        }
        else
        {
            jo.Add("children", JArray.FromObject(node.Children, serializer));
        }
        jo.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

JsonConverter を使用して、次のようにツリーを JSON にシリアル化できます。

JsonSerializerSettings settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new NodeConverter() },
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(root, settings);

Console.WriteLine(json);

出力は次のとおりです。

{
  "name": ".",
  "children": [
    {
      "name": "Shopping",
      "children": [
        {
          "name": "Housewares",
          "children": [
            {
              "name": "Kitchen supplies",
              "leaf": true
            },
            {
              "name": "Groceries",
              "leaf": true
            },
            {
              "name": "Cleaning supplies",
              "leaf": true
            },
            {
              "name": "Office supplies",
              "leaf": true
            }
          ]
        },
        {
          "name": "Remodeling",
          "children": [
            {
              "name": "Retile kitchen",
              "leaf": true
            },
            {
              "name": "Paint bedroom",
              "children": [
                {
                  "name": "Ceiling",
                  "leaf": true
                },
                {
                  "name": "Walls",
                  "leaf": true
                }
              ]
            },
            {
              "name": "Other",
              "leaf": true
            }
          ]
        }
      ]
    },
    {
      "name": "Misc",
      "leaf": true
    }
  ]
}

もう 1 つの注意事項: 上記の目的の JSONtextでは、プロパティではなくプロパティを使用してルート ノードを表示していnameますが、これは他のすべてのノードと矛盾しています。これは間違いだったと思います。そうでない場合は、JsonConverter を変更して、名前がドット ( )textの場合に代わりにプロパティを出力するロジックを持たせる必要があります。name.

お役に立てれば。

于 2013-12-07T01:55:21.010 に答える