如何使用非标准(和变化的)属性名称反序列化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)); }