在 .NET 中反序列化 json 时如何忽略丢失的节点

How to ignore missing nodes when deserialising json in .NET

某些 Shopify API 在未配置时不 return 节点,而不是 returning 空值。

JSON 示例

{
  "orders": [
    {
      "id": 1,
      "customer": {
        "id": 001,
      }
    },
    {
      "id": 2
    }
  ]
}

为了反序列化 Json,我需要在 class 对象中包含所有属性。

Public Class AllOrders
  Public Property orders() As List(Of Order)
End Class

Public Class Order
  Public Property id As Long?
  Public Property customer() As Customer
End Class

Public Class Customer
  Public Property id As Long?
End Class

如何在不使用复杂的 if 语句的情况下有效地跳过丢失的节点。

问题不在于 json 的反序列化,而是试图读取不存在的命名成员。

Dim AllOrders = JsonConvert.DeserializeObject(Of AllOrders)(GetOrders())

For Each order As Shopify.Order In AllOrders.orders
  Dim test as order.customer.id
  'Error NullReferenceException on customer
Next

这可以在 Json.Net 框架内处理吗?


JsonSerializerSettings

请注意,我已经尝试过以下设置。

Dim settings = New JsonSerializerSettings With {
  .NullValueHandling = NullValueHandling.Ignore,
  .MissingMemberHandling = MissingMemberHandling.Ignore
}

已更新以减少一些废话

Public Class AllOrders
    Public Property orders() As List(Of TestOrder)
End Class

Public Class TestOrder

    Public Property id As Long
    Public Property customer As TestCustomer

    Sub New()
        _customer = New TestCustomer()
    End Sub
End Class

Public Class TestCustomer
    Public Property id As Long
End Class


Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    Dim testString As String = <![CDATA[
        {
          "orders": [
            {
              "id": 1,
              "customer": {
                "id": 59,
              }
            },
            {
              "id": 2
            }
          ]
        }
    ]]>.Value
    Dim settings = New JsonSerializerSettings With {.NullValueHandling = NullValueHandling.Include, .MissingMemberHandling = MissingMemberHandling.Ignore}
    Dim all As AllOrders = JsonConvert.DeserializeObject(Of AllOrders)(testString, settings)

    For Each order As TestOrder In all.orders
        Dim test As Long = order.customer.id
        ' ouput is 59 and then 0 for the missing node (integer default value)
    Next
End Sub

有几个客户端选项可以在一行中处理这个问题。

您可以使用空条件运算符 ?.,如

Dim oneId = order.Customer?.Id

在这种情况下,结果是一个可为空的 Long,但 Id 已经是一个可为空的 long,因此它不应更改后续处理,因为您已经需要考虑以下可能性它可能为空。如果缺失值只有一个“合理”值,则可以使用 GetValueOrDefault 获得保证值。

您可以使用 If 运算符的空合并形式,如

Dim guaranteedCustomer = If(order.Customer, defaultCustomer)

这需要谨慎,因为使用单个可变对象作为您的默认值可能会在以后当其中一个默认值发生变化从而更改所有默认项时出现严重错误。