skip to Main Content

Some of the Shopify API’s don’t return nodes when they are not configured rather than returning null values.

JSON EXAMPLE

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

In order to deserialise the Json I need to include all properties within the class object.

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

How I can efficiently skip missing nodes without convoluted if statements.

The issue is not the deserialisation of the json but trying to read a named member that does not exist.

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

Can this be handled within the Json.Net framework?


JsonSerializerSettings

I should note I have already tried the following settings.

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

2

Answers


  1. UPDATED to reduce some of the verbiage

    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
    
    Login or Signup to reply.
  2. There are a couple of client-side alternatives for handling this in one line.

    You could use the null conditional operator ?., as in

    Dim oneId = order.Customer?.Id
    

    In this case, the result is a nullable Long, but Id is already a nullable long, so it shouldn’t change subsequent handling as you already needed to account for the possibility that it might be null. If there is a single "sensible" value for a missing value, you can then use GetValueOrDefault to have a guaranteed value.

    You could use the null coalescing form of the If operator, as in

    Dim guaranteedCustomer = If(order.Customer, defaultCustomer)
    

    This would require some caution as using a single mutable object as your default is potentially a recipe for nasty bugs later when one of the defaults gets mutated thus changing all of the defaulted items.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search