2016-11-11 42 views
7

from Answer我學會了如何在c#中展開JSON對象。 從JSON字符串:如何在C#中展開flattenned json

{"menu": { 
    "id": "file", 
    "value": "File", 
    "popup": { 
    "menuitem": [ 
     {"value": "New", "onclick": "CreateNewDoc()"}, 
     {"value": "Open", "onclick": "OpenDoc()"}, 
     {"value": "Close", "onclick": "CloseDoc()"} 
    ] 
    } 
}} 

到:

串的下面是線,而不是一個對象

menu.id:file 
menu.value:File 
menu.popup.menuitem[0].value:New 
menu.popup.menuitem[0].onclick:CreateNewDoc() 
menu.popup.menuitem[1].value:Open 
menu.popup.menuitem[1].onclick:OpenDoc() 
menu.popup.menuitem[2].value:Close 
menu.popup.menuitem[2].onclick:CloseDoc() 

現在,我想反向的過程。 我可以從這個question找到實現,但它在JavaScript中。

我如何unflatten(返回從行結構化JSON)在C#與json.net?

+0

我更新了澄清一些信息的問題 –

回答

2

我設法解決它。

以下是我的代碼結合Sarath Rachuri's flattening code

我沒有在太多的情況下測試它,所以它可能是越野車。

using Newtonsoft.Json.Linq; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text.RegularExpressions; 

namespace JSONHelper 
{ 
    class JSONFlattener 
    { 
     private enum JSONType{ 
      OBJECT, ARRAY 
     } 
     public static Dictionary<string, string> Flatten(JObject jsonObject) 
     { 
      IEnumerable<JToken> jTokens = jsonObject.Descendants().Where(p => p.Count() == 0); 
      Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) => 
      { 
       properties.Add(jToken.Path, jToken.ToString()); 
       return properties; 
      }); 
      return results; 
     } 

     public static JObject Unflatten(IDictionary<string, string> keyValues) 
     { 
      JContainer result = null; 
      JsonMergeSettings setting = new JsonMergeSettings(); 
      setting.MergeArrayHandling = MergeArrayHandling.Merge; 
      foreach (var pathValue in keyValues) 
      { 
       if (result == null) 
       { 
        result = UnflatenSingle(pathValue); 
       } 
       else 
       { 
        result.Merge(UnflatenSingle(pathValue), setting); 
       } 
      } 
      return result as JObject; 
     } 

     private static JContainer UnflatenSingle(KeyValuePair<string, string> keyValue) 
     { 
      string path = keyValue.Key; 
      string value = keyValue.Value; 
      var pathSegments = SplitPath(path); 

      JContainer lastItem = null; 
      //build from leaf to root 
      foreach (var pathSegment in pathSegments.Reverse()) 
      { 
       var type = GetJSONType(pathSegment); 
       switch (type) 
       { 
        case JSONType.OBJECT: 
         var obj = new JObject(); 
         if (null == lastItem) 
         { 
          obj.Add(pathSegment,value); 
         } 
         else 
         { 
          obj.Add(pathSegment,lastItem); 
         } 
         lastItem = obj; 
         break; 
        case JSONType.ARRAY: 
         var array = new JArray(); 
         int index = GetArrayIndex(pathSegment); 
         array = FillEmpty(array, index); 
         if (lastItem == null) 
         { 
          array[index] = value; 
         } 
         else 
         { 
          array[index] = lastItem; 
         } 
         lastItem = array; 
         break; 
       } 
      } 
      return lastItem; 
     } 

     public static IList<string> SplitPath(string path){ 
      IList<string> result = new List<string>(); 
      Regex reg = new Regex(@"(?!\.)([^. ^\[\]]+)|(?!\[)(\d+)(?=\])"); 
      foreach (Match match in reg.Matches(path)) 
      { 
       result.Add(match.Value); 
      } 
      return result; 
     } 

     private static JArray FillEmpty(JArray array, int index) 
     { 
      for (int i = 0; i <= index; i++) 
      { 
       array.Add(null); 
      } 
      return array; 
     } 

     private static JSONType GetJSONType(string pathSegment) 
     { 
      int x; 
      return int.TryParse(pathSegment, out x) ? JSONType.ARRAY : JSONType.OBJECT; 
     } 

     private static int GetArrayIndex(string pathSegment) 
     { 
      int result; 
      if (int.TryParse(pathSegment, out result)) 
      { 
       return result; 
      } 
      throw new Exception("Unable to parse array index: " + pathSegment); 
     } 

    } 
} 
0

如果我正確理解你的要求,我建議你閱讀關於JObject的文檔,在這裏你可以找到FromObject方法。這似乎是你想要的。

var result = JObject.FromObject(obj); 
var json = result.ToString(); 
0
string json = JsonConvert.SerializeObject(menu); 

獲得從NuGet包管理器NewtonSoft.Json DLL。並寫上面的那一行就是了。

-1

要扁平化JSON對象:

arrayJSON.stringify()