C# JSON 反序列化 null 嵌套属性



我一直在努力将以下JSON反序列化为C#。 从API回来的JSON有相当多的层次,所以也许我忽略了什么。

null的属性是MemberStats(在NestedStatEntries类内部(。 其他一切都还好。

杰森:

{
    "kind": "tm:ltm:pool:members:memberscollectionstats",
    "selfLink": "https://device/mgmt/tm/ltm/pool/myPoolName/members/stats?ver=12.1.2",
    "entries": {
        "https://device/mgmt/tm/ltm/pool/myPoolName/members/~Common~myPoolName/stats": {
            "nestedStats": {
                "kind": "tm:ltm:pool:members:membersstats",
                "selfLink": "https://device/mgmt/tm/ltm/pool/myPoolName/members/~Common~myPoolName/stats?ver=12.1.2",
                "entries": {
                    "activeMemberCnt": {
                        "value": 16
                    },
                    "connqAll.ageEdm": {
                        "value": 0
                    },
                    "connqAll.ageEma": {
                        "value": 0
                    },
                    "connqAll.ageHead": {
                        "value": 0
                    },
                    "connqAll.ageMax": {
                        "value": 0
                    },
                    "connqAll.depth": {
                        "value": 0
                    },
                    "connqAll.serviced": {
                        "value": 0
                    },
                    "connq.ageEdm": {
                        "value": 0
                    },
                    "connq.ageEma": {
                        "value": 0
                    },
                    "connq.ageHead": {
                        "value": 0
                    },
                    "connq.ageMax": {
                        "value": 0
                    },
                    "connq.depth": {
                        "value": 0
                    },
                    "connq.serviced": {
                        "value": 0
                    },
                    "curSessions": {
                        "value": 0
                    },
                    "minActiveMembers": {
                        "value": 0
                    },
                    "monitorRule": {
                        "description": "min 1 of /Common/prod-olbtp_https"
                    },
                    "tmName": {
                        "description": "/Common/myPoolName"
                    },
                    "serverside.bitsIn": {
                        "value": 1854170442864
                    },
                    "serverside.bitsOut": {
                        "value": 28010721155520
                    },
                    "serverside.curConns": {
                        "value": 46
                    },
                    "serverside.maxConns": {
                        "value": 350
                    },
                    "serverside.pktsIn": {
                        "value": 1486804119
                    },
                    "serverside.pktsOut": {
                        "value": 2494389460
                    },
                    "serverside.totConns": {
                        "value": 2864936
                    },
                    "status.availabilityState": {
                        "description": "available"
                    },
                    "status.enabledState": {
                        "description": "enabled"
                    },
                    "status.statusReason": {
                        "description": "The pool is available"
                    },
                    "totRequests": {
                        "value": 0
                    },
                    "https://device/mgmt/tm/ltm/pool/myPoolName/members/~Common~myPoolName/members/stats": {
                        "nestedStats": {
                            "entries": {
                                "https://device/mgmt/tm/ltm/pool/myPoolName/members/~Common~myPoolName/members/~Common~10.10.10.30:443/stats": {
                                    "nestedStats": {
                                        "entries": {
                                            "addr": {
                                                "description": "10.10.10.30"
                                            },
                                            "connq.ageEdm": {
                                                "value": 0
                                            },
                                            "connq.ageEma": {
                                                "value": 0
                                            },
                                            "connq.ageHead": {
                                                "value": 0
                                            },
                                            "connq.ageMax": {
                                                "value": 0
                                            },
                                            "connq.depth": {
                                                "value": 0
                                            },
                                            "connq.serviced": {
                                                "value": 0
                                            },
                                            "curSessions": {
                                                "value": 0
                                            },
                                            "monitorRule": {
                                                "description": "min 1 of /Common/prod-olbtp_https (pool monitor)"
                                            },
                                            "monitorStatus": {
                                                "description": "up"
                                            },
                                            "nodeName": {
                                                "description": "/Common/10.10.10.30"
                                            },
                                            "poolName": {
                                                "description": "/Common/myPoolName"
                                            },
                                            "port": {
                                                "value": 443
                                            },
                                            "serverside.bitsIn": {
                                                "value": 123606959904
                                            },
                                            "serverside.bitsOut": {
                                                "value": 1252550265608
                                            },
                                            "serverside.curConns": {
                                                "value": 4
                                            },
                                            "serverside.maxConns": {
                                                "value": 18
                                            },
                                            "serverside.pktsIn": {
                                                "value": 75556262
                                            },
                                            "serverside.pktsOut": {
                                                "value": 115991280
                                            },
                                            "serverside.totConns": {
                                                "value": 189971
                                            },
                                            "sessionStatus": {
                                                "description": "enabled"
                                            },
                                            "status.availabilityState": {
                                                "description": "available"
                                            },
                                            "status.enabledState": {
                                                "description": "enabled"
                                            },
                                            "status.statusReason": {
                                                "description": "Pool member is available"
                                            },
                                            "totRequests": {
                                                "value": 0
                                            }
                                        }
                                    }
                                },
                                "https://device/mgmt/tm/ltm/pool/myPoolName/members/~Common~myPoolName/members/~Common~10.10.10.40:443/stats": {
                                    "nestedStats": {
                                        "entries": {
                                            "addr": {
                                                "description": "10.10.10.40"
                                            },
                                            "connq.ageEdm": {
                                                "value": 0
                                            },
                                            "connq.ageEma": {
                                                "value": 0
                                            },
                                            "connq.ageHead": {
                                                "value": 0
                                            },
                                            "connq.ageMax": {
                                                "value": 0
                                            },
                                            "connq.depth": {
                                                "value": 0
                                            },
                                            "connq.serviced": {
                                                "value": 0
                                            },
                                            "curSessions": {
                                                "value": 0
                                            },
                                            "monitorRule": {
                                                "description": "min 1 of /Common/prod-olbtp_https (pool monitor)"
                                            },
                                            "monitorStatus": {
                                                "description": "up"
                                            },
                                            "nodeName": {
                                                "description": "/Common/10.10.10.40"
                                            },
                                            "poolName": {
                                                "description": "/Common/myPoolName"
                                            },
                                            "port": {
                                                "value": 443
                                            },
                                            "serverside.bitsIn": {
                                                "value": 70383109304
                                            },
                                            "serverside.bitsOut": {
                                                "value": 1114184738168
                                            },
                                            "serverside.curConns": {
                                                "value": 3
                                            },
                                            "serverside.maxConns": {
                                                "value": 32
                                            },
                                            "serverside.pktsIn": {
                                                "value": 58376213
                                            },
                                            "serverside.pktsOut": {
                                                "value": 98729511
                                            },
                                            "serverside.totConns": {
                                                "value": 103410
                                            },
                                            "sessionStatus": {
                                                "description": "enabled"
                                            },
                                            "status.availabilityState": {
                                                "description": "available"
                                            },
                                            "status.enabledState": {
                                                "description": "enabled"
                                            },
                                            "status.statusReason": {
                                                "description": "Pool member is available"
                                            },
                                            "totRequests": {
                                                "value": 0
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

C# 包装器:

public class PoolAndMemberStatistics
{
    [JsonProperty("entries")]
    public Dictionary<string, EntriesWrapper> Entries { get; set; }
    [JsonProperty("generation")]
    public long Generation { get; set; }
    [JsonProperty("kind")]
    public string Kind { get; set; }
    [JsonProperty("selfLink")]
    public string SelfLink { get; set; }
    public partial class EntriesWrapper
    {
        [JsonProperty("nestedStats")]
        public NestedStats NestedStats { get; set; }
    }
    public partial class NestedStats
    {
        [JsonProperty("entries")]
        public NestedStatEntries Entries { get; set; }
        [JsonProperty("kind")]
        public string Kind { get; set; }
        [JsonProperty("selfLink")]
        public string SelfLink { get; set; }
    }
    public partial class NestedStatEntries
    {
        [JsonProperty("nestedStats")]
        public Dictionary<string, NestedStats> MemberStats { get; set; }
        [JsonProperty("activeMemberCnt")]
        public Dictionary<string, long> ActiveMemberCnt { get; set; }
        [JsonProperty("connq.ageEdm")]
        public Dictionary<string, long> ConnqAgeEdm { get; set; }
        [JsonProperty("connq.ageEma")]
        public Dictionary<string, long> ConnqAgeEma { get; set; }
        [JsonProperty("connq.ageHead")]
        public Dictionary<string, long> ConnqAgeHead { get; set; }
        [JsonProperty("connq.ageMax")]
        public Dictionary<string, long> ConnqAgeMax { get; set; }
        [JsonProperty("connqAll.ageEdm")]
        public Dictionary<string, long> ConnqAllAgeEdm { get; set; }
        [JsonProperty("connqAll.ageEma")]
        public Dictionary<string, long> ConnqAllAgeEma { get; set; }
        [JsonProperty("connqAll.ageHead")]
        public Dictionary<string, long> ConnqAllAgeHead { get; set; }
        [JsonProperty("connqAll.ageMax")]
        public Dictionary<string, long> ConnqAllAgeMax { get; set; }
        [JsonProperty("connqAll.depth")]
        public Dictionary<string, long> ConnqAllDepth { get; set; }
        [JsonProperty("connqAll.serviced")]
        public Dictionary<string, long> ConnqAllServiced { get; set; }
        [JsonProperty("connq.depth")]
        public Dictionary<string, long> ConnqDepth { get; set; }
        [JsonProperty("connq.serviced")]
        public Dictionary<string, long> ConnqServiced { get; set; }
        [JsonProperty("curSessions")]
        public Dictionary<string, long> CurSessions { get; set; }
        [JsonProperty("minActiveMembers")]
        public Dictionary<string, long> MinActiveMembers { get; set; }
        [JsonProperty("monitorRule")]
        public Dictionary<string, string> MonitorRule { get; set; }
        [JsonProperty("serverside.bitsIn")]
        public Dictionary<string, long> ServersideBitsIn { get; set; }
        [JsonProperty("serverside.bitsOut")]
        public Dictionary<string, long> ServersideBitsOut { get; set; }
        [JsonProperty("serverside.curConns")]
        public Dictionary<string, long> ServersideCurConns { get; set; }
        [JsonProperty("serverside.maxConns")]
        public Dictionary<string, long> ServersideMaxConns { get; set; }
        [JsonProperty("serverside.pktsIn")]
        public Dictionary<string, long> ServersidePktsIn { get; set; }
        [JsonProperty("serverside.pktsOut")]
        public Dictionary<string, long> ServersidePktsOut { get; set; }
        [JsonProperty("serverside.totConns")]
        public Dictionary<string, long> ServersideTotConns { get; set; }
        [JsonProperty("status.availabilityState")]
        public Dictionary<string, string> StatusAvailabilityState { get; set; }
        [JsonProperty("status.enabledState")]
        public Dictionary<string, string> StatusEnabledState { get; set; }
        [JsonProperty("status.statusReason")]
        public Dictionary<string, string> StatusStatusReason { get; set; }
        [JsonProperty("tmName")]
        public Dictionary<string, string> TmName { get; set; }
        [JsonProperty("totRequests")]
        public Dictionary<string, long> TotRequests { get; set; }
    }
}

事实上,这种 JSON 结构乍一看似乎不是很友好。 它绝对无视使用 json2csharp.com 等工具生成代码。 但仔细观察,看起来我们这里有一个递归结构,可以归结为两个类。 首先,我们有一个 Statistics 类,它有一个 Entries 字典(以及其他几个可选属性(。 其次,我们有一个Entry类,它包含一个数字Value,一个字符串Description或一个NestedStats,后者是一个Statistics实例。

class Statistics
{
    [JsonProperty("entries")]
    public Dictionary<string, Entry> Entries { get; set; }
    [JsonProperty("kind")]
    public string Kind { get; set; }
    [JsonProperty("selfLink")]
    public string SelfLink { get; set; }
}
class Entry
{
    [JsonProperty("value")]
    public long Value { get; set; }
    [JsonProperty("description")]
    public string Description { get; set; }
    [JsonProperty("nestedStats")]
    public Statistics NestedStats { get; set; }
}

对于Entry类,我可能会添加一个只读EntryType属性来指示填充了三个值中的哪一个,但这是可选的。

enum EntryType { Value, Description, NestedStats }
class Entry
{
    ...
    public EntryType EntryType
    {
        get
        {
            if (NestedStats != null) return EntryType.NestedStats;
            if (Description != null) return EntryType.Description;
            return EntryType.Value;
        }
    }
}

您可以像这样反序列化整个 JSON 结构:

Statistics stats = JsonConvert.DeserializeObject<Statistics>(json);

(与评论中所说的相反,Json.Net 可以很好地处理递归结构。

小提琴:https://dotnetfiddle.net/aB1qbn

最新更新