使用c#访问复杂的JSON内部对象deserilization

时间:2018-03-16 14:37:10

标签: c# json asp.net-web-api deserialization

我有一个COMPLEX JSON,我需要反序列化并访问其所有对象。我的JSON看起来像这样

{
    "name": {},
    "percentage": [
        {
            "math": {
                "2.503300099.1": 460800,
                "2.503300099.2": 460800,
                "2.503300099.3": 460800,
                "2.503308292.1": 2457600,
                "2.503308292.2": 2457600,
                "2.503308292.3": 2457600
            },
            "english": {
                "2.503300099": "hello",
                "2.503308292": "hi"
            },

            "exam": "2.0"
        }
    ],
    "class": {},
    "section": "7.17.1",
    "total": 1
}

JSON的值可能会改变,它们出现的次数也可能会改变。

到目前为止我可以访问的是名称,类别,部分,总数和问题是百分比部分。我也可以达到百分比,但我无法访问数学或英语,或者考试他们的价值观。

string content = await response.Content.ReadAsStringAsync();                 
  JObject Search = JObject.Parse(content);                  
  Speed res = new Speed();

res.class= Search["class"].ToString();  // good
res.english = Search["english"].ToString();// not good

请提供任何帮助或建议吗?

修改

在关于JSON结构的这么多问题之后,我想澄清一下这个结构不会改变,但是对象的数量可能会让我们用一个例子来理解:

{
    "One": {},
    "Two": [
        {
            "twoA": {
                "2.503300099.1": 460800,
                "2.503300099.2": 460800,
                 "...." : ...,
                 "...." : ...,
            },
            "TwoB": {
                "2.503300099": "value",
                "2.503308292": "value"
                "...." : ...,
                "...." : ...,
            },
             "TwoC": {
                "2.503300099": "value",
                "2.503308292": "value"
                "...." : ...,
                "...." : ...,
            },
            "exam": "2.0",
            "...." : ...,
            "...." : ...,
        }
    ],
    "Three": {empty},
    "Four": "value string",
    "Five": value int
    .....
    .....
}

希望这能澄清对JSON结构的怀疑

1 个答案:

答案 0 :(得分:1)

从对您的问题和后续答案的评论来看,似乎来自API的数据是不可预测的,因为我开始争论负责该API的人应该退后一步并重新考虑他们的方法。我没有看到如何解析任何数据,而没有提示如何构建数据。

但也许我反应过度了......

也许将数据解析为dynamic是您正在寻找的答案?使用这种方法,您可以执行以下操作:

const string data = "{\"1123.5433\":{\"42.42.42\":\"bazinga\"}}";
var myDynamic = JsonConvert.DeserializeObject<dynamic>(data);

Console.WriteLine(myDynamic["1123.5433"]["42.42.42"]); // -> bazinga;

示例中math中值的路径,如果我没记错的话,就像这样:

myDynamic["percentage"][0]["math"]["2.503300099.1"]; // ~ 460800?

虽然不太可读。还是稳定的所以,我居住,回过头来思考我最初的困惑,那就是有什么样的生物想到了有问题的API ......

编辑:更新以反映原始问题中的评论和更改:

// First example
const string originalExample =
    "{\"name\": {},\"percentage\": [{\"math\": {\"2.503300099.1\": 460800,\"2.503300099.2\": 460800},\"english\": {\"2.503300099\": \"hello\"}}]}";
var myFirstDynamic = JsonConvert.DeserializeObject<dynamic>(originalExample);

Console.WriteLine(myFirstDynamic["percentage"][0]["math"]["2.503300099.1"]); // -> 460800

// Second example
const string newExample =
            "{\"One\": {},\"Two\": [{\"twoA\": {\"2.503300099.1\": 460800,\"2.503300099.2\": 460800,},\"TwoB\": {\"2.503300099\": \"value\",\"2.503308292\": \"value\"},\"TwoC\": {\"2.503300099\": \"value\",\"2.503308292\": \"value\"},\"exam\": \"2.0\"}]}";
var mySecondDynamic = JsonConvert.DeserializeObject<dynamic>(newExample);

Console.WriteLine(mySecondDynamic["Two"][0]["twoA"]["2.503300099.1"]); // -> 460800;

鉴于您在第二个示例中提供的结构,您还可以定义合适的类型以适合相同的结构:

public class MyObject
{
    public IEnumerable<MyNextObject> Two { get; set; }
}

public class MyNextObject
{
    public dynamic twoA { get; set; }
}

然后你可以像这样反序列化和解析:

var deserializedToType = JsonConvert.DeserializeObject<MyObject>(newExample);
Console.WriteLine(deserializedToType.Two.First().twoA["2.503300099.1"]); // -> 460800;

由于源数据中的属性名称对C#无效,因此您仍需要在出现问题的地方输入dynamic(例如MyNextObject.twoA)。此外,根据您正在尝试做的事情以及在什么情况下,枚举percentage等子项可能是比选择特定索引更好的选择。

请注意,我使用的是与我在所有示例中提供的完全相同的json结构,虽然为了简洁而最终缩短并转义为提供工作示例。

如果您的源属性名称不一致,无效或不遵守常见的实践,为了保持您的C#代码干净,您应该使用某种方法在源和目标之间映射值。例如。如果你正在使用Json.NET,那就像JsonProperty属性。

另外,请注意,我不是在这里展示“代码生产”。显然,您应该注意并妥善处理潜在问题,例如null值或超出范围的索引。