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

时间:2015-11-17 06:29:09

标签: c# .net json serialization

我必须读取一个JSON流(我无法控制),其格式为:

{"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)有字符的名字可以&# 39;用于C#属性。

如何反序列化?

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

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

3 个答案:

答案 0 :(得分:3)

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

public class RootObject
{
    public Dictionary<string, PathData> 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<RootObject>(jsonString, settings);

使用辅助方法:

public static class DataContractJsonSerializerHelper
{
    public static T GetObject<T>(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<T>(string json, DataContractJsonSerializerSettings settings)
    {
        return GetObject<T>(json, new DataContractJsonSerializer(typeof(T), settings));
    }

    private static MemoryStream GenerateStreamFromString(string value)
    {
        return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
    }
}

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

        var root = JsonConvert.DeserializeObject<RootObject>(jsonString);

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

答案 1 :(得分:1)

我们需要先将此无效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; }
}

答案 2 :(得分:0)

假设您有一个有效的JSON,您可以使用https://developer.apple.com/app-store/review/rejections/ https://developer.apple.com/app-store/review/guidelines/ 返回一个对象列表

JavaScriptSerializer

或者,您可以将string json = "{}" var serializer = new JavaScriptSerializer(); var deserializedValues = (Dictionary<string, object>)serializer.Deserialize(json, typeof(object)); 指定为类型参数

Dictionary<string, List<string>>