从c#模型创建嵌套的json对象

时间:2017-08-02 11:04:56

标签: c# json.net

这是我的json:

[
   {
      "ChangeFlowsFromParent":"false",
      "ChangeFlowsToParent":"true",
      "StreamType":"mainine",
      "streamName":"ArgOS_2_0",
      "Parent":"none",
      "Compliance":"Released",
      "children":[
         {
            "ChangeFlowsFromParent":"true",
            "ChangeFlowsToParent":"true",
            "StreamType":"Release",
            "streamName":"ArgOS_2_0_DHAL1",
            "Parent":"ArgOS_2_0",
            "Compliance":"Released",
            "children":[
               {
                  "ChangeFlowsFromParent":"false",
                  "ChangeFlowsToParent":"true",
                  "StreamType":"Release",
                  "streamName":"ArgOS_child_DHAL2",
                  "Parent":"ArgOS_2_0_DHAL1",
                  "Compliance":"Released",
                  "children":[
                     {
                        "ChangeFlowsFromParent":"false",
                        "ChangeFlowsToParent":"true",
                        "StreamType":"Release",
                        "streamName":"ArgOS_child_Gen2",
                        "Parent":"ArgOS_child_DHAL2",
                        "Compliance":"Released"
                     }
                  ]
               }
            ]
         },
         {
            "ChangeFlowsFromParent":"true",
            "ChangeFlowsToParent":"true",
            "StreamType":"Release",
            "streamName":"ArgOS_2_0_DHAL2",
            "Parent":"ArgOS_2_0",
            "Compliance":"NA"
         },
         {
            "ChangeFlowsFromParent":"false",
            "ChangeFlowsToParent":"false",
            "StreamType":"Release",
            "streamName":"ArgOS_2_0_DHAL3",
            "Parent":"ArgOS_2_0",
            "Compliance":"NA"
         }
      ]
   }
]

这是我的模特

public class TreeModel
{
    public string StreamName { get; set; }
    public string ParentName { get; set; }
    public string StreamType { get; set; }
    public bool ChangeFlowsFromParent { get; set; }
    public bool ChangeFlowsToParent { get; set; }
    public string Compliance { get; set; }
    public string Parent { get; set; }

}

所以我有一个模型形式的数据,我需要创建一个像上面提到的嵌套Json结构。 基于parent = streamname,必须创建一个子标记,并将该模型项添加为json数组。

这个JSON适用于我的树形图。这怎么可以实现?

2 个答案:

答案 0 :(得分:3)

每当您必须序列化数据设计时,类结构将完全符合预期的im- / export结构。不要关心你的其他应用程序,只关注im- / export。

给定的JSON可以用

表示
class TreeModelJson
{
    [JsonProperty("ChangeFlowsFromParent")]
    public string ChangeFlowsFromParent { get; set; }
    [JsonProperty("ChangeFlowsToParent")]
    public string ChangeFlowsToParent { get; set; }
    [JsonProperty("StreamType")]
    public string StreamType { get; set; }
    [JsonProperty("streamName")]
    public string StreamName { get; set; }
    [JsonProperty("Parent")]
    public string Parent { get; set; }
    [JsonProperty("Compliance")]
    public string Compliance { get; set; }
    [JsonProperty("children", NullValueHandling = NullValueHandling.Ignore)]
    public ICollection<TreeModelJson> Children { get; set; }
}

现在是时候将应用程序模型中的mapper写入JSON模型

static ICollection<TreeModelJson> MapToTreeModelJsonCollection(ICollection<TreeModel> source)
{
    // map all items
    var allItems = source.Select(e => new TreeModelJson
    {
        ChangeFlowsFromParent = e.ChangeFlowsFromParent.ToString().ToLower(),
        ChangeFlowsToParent = e.ChangeFlowsToParent.ToString().ToLower(),
        Compliance = e.Compliance,
        Parent = e.Parent ?? "none",
        StreamName = e.StreamName,
        StreamType = e.StreamType,
    }).ToList();

    // build tree structure
    foreach (var item in allItems)
    {
        var children = allItems.Where(e => e.Parent == item.StreamName).ToList();
        if (children.Any())
        {
            item.Children = children;
        }
    }

    // return only root items
    return allItems.Where(e => e.Parent == "none").ToList();
}

现在是时候把它们放在一起了

var source = new List<TreeModel>
{
    ... // populate some data
};
var output = MapToTreeModelJsonCollection(source);
var json = JsonConvert.SerializeObject(output,Formatting.Indented);

Complete example on .net fiddle

一些注释

  • JSON中的Parent属性是多余的,因为如果对象是另一个对象的子对象,则已经给出了此信息

  • JSON知道boolean属性,最好将它们反序列化为boolean而不是string

答案 1 :(得分:0)

有很大的优势来优化这个,但如果不是那么大的阵列就不需要进行微优化。

/// <summary>
/// Creates a JObject from the tree node
/// </summary>
/// <param name="treeModel">The node to serialize</param>
/// <param name="context">All items</param>
/// <returns></returns>
public static JObject CreateJObject(TreeModel treeModel,IList<TreeModel> context) 
{
    JObject result = JObject.FromObject(treeModel);

    //This is not really needed but will cut the size of array for next iterations
    context.Remove(treeModel);

    //Used stream for the primary key.
    result["children"] = GetChildren(treeModel.StreamName, context);

    return result;
}

/// <summary>
/// Gets the children of the parent from context object
/// </summary>
/// <param name="id">id of the node</param>
/// <param name="context">All the nodes to read the children from</param>
/// <returns></returns>
public static JArray GetChildren(string id, IList<TreeModel> context) 
{
    //I used Parent for the forign key for the 
    return new JArray(context.Where(c => c.Parent == id).ToArray().Select(c => CreateJObject(c, context)));
} 

我在类似的东西上测试了它

 var items = new[] 
            {
                 new TreeModel{ StreamName = "a" },
                 new TreeModel{ StreamName = "b" , Parent = "a" },
                 new TreeModel{ StreamName = "c" , Parent = "a" },
                 new TreeModel{ StreamName = "d" , Parent = "b" }
            };

            //A list of all object I use a copy to remove already added items
        var context = items.ToList();

        //Gets the root elements the ones that have no parents
        var root = items.Where(tm => String.IsNullOrEmpty(tm.Parent) || tm.Parent == "none").Select(tm => CreateJObject(tm, context));    
            var data = new JArray(root);

            Console.WriteLine(data.ToString());

正如我已经提到的,还有优化空间,但这可以完成工作。

注意 在程序中使用节点删除还可以为您提供可能遇到的其他问题的解决方案,但不包括具有父ID但父节点的节点的问题。如果在序列化后查看上下文,它将为您提供所有具有父节点但父节点不在原始列表中的节点,换句话说是未序列化的节点。