将嵌套JSON反序列化为列表

时间:2015-03-20 21:48:57

标签: c# json asp.net-mvc json-deserialization

我正在尝试在我的视图中将下拉列表与这些列表绑定。无法将以下JSON集合转换为LISTS。

我的JSON字符串采用以下格式:

 ["AppTypes",
 [
    {
        "AppTypeID": "5136",
        "AppType": "ABC"
    },
    {
        "AppTypeID": "dca6",
        "AppType": "MNO"
    },
    {
        "AppTypeID": "d8de",
        "AppType": "PQR"
    }
],
"CompTypes",
[
    {
        "CompTypeID": "0425",
        "CompType": "STU"
    },        
    {
        "CompTypeID": "0426",
        "CompType": "EDC"
    },
    {
        "CompTypeID": "0444",
        "CompType": "PLM"
    }
]
]

我正在尝试反序列化代码,但没有通过。我的班级,

     public class DAL
     {
           public DAL() { }
           public CompList CompList { get; set; }
     }

     public class CompList
     {
         public CompList()
         {
              AppTypes = new List<AppTypes>();
              CompType = new List<CompTypes>();                   
         }
         public List<AppTypes> AppTypes;
         public List<ComTypes> CompType;
     }
     public class AppTypes
     {
         public Guid AppTypeID { get; set; }
         public string AppType { get; set; }
     }

     public class CompTypes
     {
         public Guid CompTypeID { get; set; }
         public string CompType { get; set; }
     }

     public class JSONSerializer
     {
          public static T ConvertFromJSON<T>(String json)
          {
              JavaScriptSerializer serializer = new JavaScriptSerializer();
              return serializer.Deserialize<T>(json);
          }
     }

控制器代码:

    dynamic obj = JSONSerializer.ConvertFromJSON<DAL>(JsonData);

无法找到我错的地方。任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:2)

这里的主要问题是您的JSON表示包含字符串或包含对象的嵌套数组的顶级数组,但您尝试将其反序列化为顶级对象 - 而不是数组。你的类设计是非常合理的,但是JavaScriptSerializer之类的序列化器并不是真正设计用于在反序列化期间以这种方式完全重构数据模型。您可能需要反序列化为JSON的更多文字表示,然后使用Linq重组数据。

第二个问题是您声明ID属性为Guids,但相应的JSON属性(例如"AppTypeID": "5136")没有足够的数字作为Guids。 JavaScriptSerializer要求Guid为have 32 digits, optionally separated by hyphens,例如:"d70d7583-b2e6-4f6e-8d99-2022d3ca2b10""d70d7583b2e64f6e8d992022d3ca2b10"

因此,如果我将Guid属性更改为字符串:

public class AppTypes
{
    public string AppTypeID { get; set; }
    public string AppType { get; set; }
}

public class CompTypes
{
    public string CompTypeID { get; set; }
    public string CompType { get; set; }
}

然后我可以反序列化并转换为CompList,如下所示:

        var js = new JavaScriptSerializer();
        var array = js.Deserialize<List<object>>(JsonData); // Deserialize outer array
        var compList = new CompList
        {
            AppTypes = array
                .OfType<IEnumerable<object>>()          // Enumerate through nested arrays
                .SelectMany(o => o)                     // Enumerate through elements in nested arrays
                .OfType<IDictionary<string, object>>()  // Pick out those which are JSON objects (deserialized as dictionaries)
                .Where(d => d.ContainsKey("AppType"))   // Filter those that are AppTypes 
                .Select(d => js.ConvertToType<AppTypes>(d)) // Deserialize to the AppTypes class
                .ToList(),
            CompType = array
                .OfType<IEnumerable<object>>()
                .SelectMany(o => o)
                .OfType<IDictionary<string, object>>()
                .Where(d => d.ContainsKey("CompType"))
                .Select(d => js.ConvertToType<CompTypes>(d))
                .ToList(),
        };

仅供参考,您的原始代码可以将看起来像这样的JSON反序列化为CompList

{
  "AppTypes": [
    {
      "AppTypeID": "5136",
      "AppType": "ABC"
    },
    {
      "AppTypeID": "dca6",
      "AppType": "MNO"
    },
    {
      "AppTypeID": "d8de",
      "AppType": "PQR"
    }
  ],
  "CompType": [
    {
      "CompTypeID": "0425",
      "CompType": "STU"
    },
    {
      "CompTypeID": "0426",
      "CompType": "EDC"
    },
    {
      "CompTypeID": "0444",
      "CompType": "PLM"
    }
  ]
}

请注意,最外面的JSON是一个具有两个数组值属性的对象,而不是一个包含两个字符串和两个数组的数组。