2017-08-02 42 views
0

嵌套JSON对象这是我的JSON:创建从C#模型

[ 
    { 
     "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是我的树形图。这是如何实现的?

+0

请格式化您的json,它现在是不可读的。 – Glubus

+0

构建一个代表JSON的类,用数据填充类并反序列化它。 –

+0

很抱歉,streamName是primaryKey,并且您希望单个对象具有相同的密钥的所有对象? –

回答

2

无论何时您需要序列化数据,都会设计一个完全符合预期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; } 
} 

表示现在是时候从你的应用程序模型的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

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,但不包括父节点的问题。如果您在序列化之后查看上下文,它将为您提供具有父代的所有节点,但父代不在原始列表中,也就是说没有序列化的节点。