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

C# 如何使用非标准(和可变)属性名(在.NET中)反序列化JSON,c#,.net,json,serialization,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", "dat

我必须读取一个我无法控制的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个带有字符的名称,这些字符不能在C属性中使用

我如何反序列化这个

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


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

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

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

strign json = "{}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var deserializedValues = serializer.Deserialize<Dictionary<string, List<string>>>(json);

foreach (KeyValuePair<string, List<string>> kvp in deserializedValues)
{
    Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value));
}

我们需要首先将这个无效的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属性名称键入的字典:

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; }
}
使用helper方法:

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 ?? ""));
    }
}
或者,您可以执行以下操作:


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

这甚至不是有效的Json。您确定这就是您需要支持的吗?您可以将JSON对象反序列化为字典。它允许不同的键名、不同的数字和名称,而这些都不能在C属性中使用。但是,提供的字符串不是JSON。您可能需要使用JSON.NET进行调查。您的JSON属性没有按照{files:{…}的要求正确地用引号括起来。看见Json.NET将解析带有属性名称引号的Json,因此如果无法修复Json,则可能需要使用它。JavaScriptSerializer可能会对Json验证有点挑剔。确保将JSON字符串用引号括起来。{files:{some_file_path.ext:{size:1000,data:xxx,data2:yyy},other_file_path.ext:{size:2000,data:xxx,data2:yyy},other_file_path.ext:{size:3000,data:xxx,data2:yyy}}}@dbc——最好的答案似乎是使用Json.NET,它显然与可移植库兼容。把它写下来作为答案,我会接受的。注意,实际数据包含所有的引号;我刚从示例中删除了它们,因为该部分不是问题所在,但是System.Web.Script.Serialization.JavaScriptSerializer在可移植库中不可用。您必须添加对的引用,但我不确定它是否在可移植库中可用。右键单击项目->选择“属性”->选择“引用”->“添加”->“程序集”->“框架”->向下滚动到“System.Web.Extensions”,并选中其旁边的框。
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 ?? ""));
    }
}
        var root = JsonConvert.DeserializeObject<RootObject>(jsonString);