如何使用非标准(和变化的)属性名称反序列化JSON(在.NET中)

我必须读取一个JSON流(我无法控制),其forms如下:

{"files": { "/some_file_path.ext": {"size":"1000", "data":"xxx", "data2":"yyy"}, "/other_file_path.ext": {"size":"2000", "data":"xxx", "data2":"yyy"}, "/another_file_path.ext": {"size":"3000", "data":"xxx", "data2":"yyy"}, } } 

所以,我有一个名为files的对象,它有许多属性,每次都有1)不同的名称,2)每次都有不同的数量,3)具有不能在C#属性中使用的字符的名称。

我该如何反序列化?

我把它放到一个可移植的库中,所以我不能在System.Web.Script.Serialization中使用JavaScriptSerializer,而且我不确定JSON.NET。 我希望使用标准的DataContractJsonSerializer。


更新:我已经将示例数据更改为更接近实际数据,并更正了不重要的区域中的JSON语法。 (仍然简化了很多,但其他部分相当标准)

您可以将"files"对象建模为由JSON属性名称键入的Dictionary

 public class RootObject { public Dictionary files { get; set; } } public class PathData { public int size { get; set; } public string data { get; set; } public string data2 { get; set; } } 

然后, 只有在使用.Net 4.5或更高版本时 ,才能使用DataContractJsonSerializer反序列化,但必须首先设置DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true

  var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }; var root = DataContractJsonSerializerHelper.GetObject(jsonString, settings); 

使用辅助方法:

 public static class DataContractJsonSerializerHelper { public static T GetObject(string json, DataContractJsonSerializer serializer = null) { using (var stream = GenerateStreamFromString(json)) { var obj = (serializer ?? new DataContractJsonSerializer(typeof(T))).ReadObject(stream); return (T)obj; } } public static T GetObject(string json, DataContractJsonSerializerSettings settings) { return GetObject(json, new DataContractJsonSerializer(typeof(T), settings)); } private static MemoryStream GenerateStreamFromString(string value) { return new MemoryStream(Encoding.Unicode.GetBytes(value ?? "")); } } 

或者,您可以安装Json.NET并执行:

  var root = JsonConvert.DeserializeObject(jsonString); 

Json.NET自动将字典序列化为JSON对象,而无需更改设置 。

我们需要先将此无效JSON转换为有效JSON。 所以有效的JSON应该是这样的

 { "files": { "FilePath" : "C:\\some\\file\\path", "FileData" : { "size": 1000, "data": "xxx", "data2": "yyy" }, "FilePath" :"C:\\other\\file\\path", "FileData" : { "size": 2000, "data": "xxx", "data2": "yyy" }, "FilePath" :"C:\\another\\file\\path", "FileData" : { "size": 3000, "data": "xxx", "data2": "yyy" } } } 

为了使它成为有效的JSON,我们可能会使用一些字符串函数使其看起来如上所示。 如

 MyJSON = MyJSON.Replace("\\", "\\\\"); MyJSON = MyJSON.Replace("files", "\"files\""); MyJSON = MyJSON.Replace("data:", "\"data:\""); MyJSON = MyJSON.Replace("data2", "\"data2\""); MyJSON = MyJSON.Replace(": {size", ",\"FileData\" : {\"size\""); MyJSON = MyJSON.Replace("C:", "\"FilePath\" :\"C:"); 

我们可以创建一个像下面这样的类来阅读

 public class FileData { public int size { get; set; } public string data { get; set; } public string data2 { get; set; } } public class Files { public string FilePath { get; set; } public FileData FileData { get; set; } } public class RootObject { public Files files { get; set; } } 

假设您有一个有效的JSON,您可以使用JavaScriptSerializer返回一个对象列表

 string json = "{}" var serializer = new JavaScriptSerializer(); var deserializedValues = (Dictionary)serializer.Deserialize(json, typeof(object)); 

或者,您可以将Dictionary>为类型参数

 strign json = "{}"; JavaScriptSerializer serializer = new JavaScriptSerializer(); var deserializedValues = serializer.Deserialize>>(json); foreach (KeyValuePair> kvp in deserializedValues) { Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value)); }