C# 如何在动态解析JSON后确定中是否存在节点

C# 如何在动态解析JSON后确定中是否存在节点,c#,json,json.net,C#,Json,Json.net,我有下面一段代码,它从事件中心读取传入消息并将其存储在blob存储中 dynamic msg = JObject.Parse(myEventHubMessage); WriteToBlob(msg, enqueuedTimeUtc, myEventHubMessage, binder, log); 以下是我收到的一些JSON示例: { "deviceId": "ATT", "product": "testprod", "data": { "001": 1, "002

我有下面一段代码,它从事件中心读取传入消息并将其存储在blob存储中

dynamic msg = JObject.Parse(myEventHubMessage);
WriteToBlob(msg, enqueuedTimeUtc, myEventHubMessage, binder, log);
以下是我收到的一些JSON示例:

{
  "deviceId": "ATT",
  "product": "testprod",
  "data": {
    "001": 1,
    "002": 3.1,
    "003": {
      "lat": 0,
      "lng": 0
    },
    "000": -80
  },
  "ts": "2020-01-27T19:29:34Z"
}
现在,代替JSON中的“数据”节点,有时设备发送名为“data_in”的节点。ts字段有时可以位于节点中的数据或数据_的内部或外部,也可以命名为timestamp。如何有效地确定节点是否存在

我想做这样的事情:

if (msg.data_in.ts != null)
{
}

在所有情况下我都会这么做。有没有办法更好地实现这一点?另外,如果我检查msg.data\u in.ts if data\u in节点不存在,if条件将失败。

您的问题是您已将
作业对象
向上转换为
动态
。这使得事情变得困难,原因如下:

  • 您失去了所有编译时代码正确性检查

  • 您无法方便地访问其自身的方法和属性(与动态提供的JSON属性相反)

    由于
    JObject
    实现了诸如
    IDictionary
    之类的接口,将其保留为类型化对象将使检查、添加和删除select JSON属性的工作更加容易

要了解为什么使用类型化的
JObject
更容易,请首先介绍以下扩展方法以方便使用:

public static class JsonExtensions
{
    public static JProperty Rename(this JProperty old, string newName)
    {
        if (old == null)
            throw new ArgumentNullException();
        var value = old.Value;
        old.Value = null;   // Prevent cloning of the value by nulling out the old property's value.
        var @new = new JProperty(newName, value);
        old.Replace(@new);  // By using Replace we preserve the order of properties in the JObject.
        return @new;
    }

    public static JProperty MoveTo(this JToken token, JObject newParent)
    {
        if (newParent == null || token == null)
            throw new ArgumentNullException();
        var toMove = (token as JProperty ?? token.Parent as JProperty);
        if (toMove == null)
            throw new ArgumentException("Incoming token does not belong to an object.");
        if (toMove.Parent == newParent)
            return toMove;
        toMove.Remove();
        newParent.Add(toMove);
        return toMove;
    }
}
现在,您可以按如下方式规范消息:

var msg = JObject.Parse(myEventHubMessage);

msg.Property("data_in")?.Rename("data"); // Normalize the name "data_in" to be "data".
msg["data"]?["ts"]?.MoveTo(msg);         // Normalize the position of the "ts" property, it should belong to the root object
msg["data"]?["timestamp"]?.MoveTo(msg);  // Normalize the position of the "timestamp" property, it should belong to the root object
msg.Property("timestamp")?.Rename("ts"); // And normalize the name of the "timestamp" property, it should be "ts".
演示小提琴

var msg = JObject.Parse(myEventHubMessage);

msg.Property("data_in")?.Rename("data"); // Normalize the name "data_in" to be "data".
msg["data"]?["ts"]?.MoveTo(msg);         // Normalize the position of the "ts" property, it should belong to the root object
msg["data"]?["timestamp"]?.MoveTo(msg);  // Normalize the position of the "timestamp" property, it should belong to the root object
msg.Property("timestamp")?.Rename("ts"); // And normalize the name of the "timestamp" property, it should be "ts".