asp.netjsonvb.netjson.netjquery-query-builder

Deserializing JSON nested arrays


I have a JSON string that I am trying to deserialize to a .Net object.

The code works, until it hits a nested array. Then it just returns empty values.
In the below example, when I debug and view the processed object, it will just have:

Rules:

0:  Will contain all data for the first node (project_number)  
1:  Will contain all data for the second node (agreement_number)  
2:  All fields will be Nothing  

Condition: AND  
Valid: true  

How do I deserialize the entire object? Please note, the JSON string comes from a library (https://querybuilder.js.org/) so I am hesitant to muck around with how the string is created.

Here is my code:

 Dim TestObj = JsonConvert.DeserializeObject(Of List(Of JsonObject))(TestString)

<Serializable()>
Public Class JsonObject
    Public Property condition As String
    Public Property Rules As List(Of Rules)
    Public Property valid As Boolean
End Class

<Serializable()>
Public Class Rules
    Public Property id As String
    Public Property field As String
    Public Property type As String
    Public Property input As String
    Public Property [operator] As String
    Public Property value As String
End Class

Public Property TestString As String = "[
{
   'condition':'AND',
   'rules':[
      {
         'id':'project_number',
         'field':'project_number',
         'type':'string',
         'input':'text',
         'operator':'equal',
         'value':'dfgdfs'
      },
      {
         'id':'agreement_number',
         'field':'agreement_number',
         'type':'string',
         'input':'text',
         'operator':'contains',
         'value':'asdfas'
      },
      {
         'condition':'AND',
         'rules':[
            {
               'id':'division',
               'field':'division',
               'type':'string',
               'input':'select',
               'operator':'in',
               'value':[
                  '0',
                  '11719'
               ]
            },
            {
               'condition':'AND',
               'rules':[
                  {
                     'id':'ta',
                     'field':'ta',
                     'type':'string',
                     'input':'select',
                     'operator':'in',
                     'value':[
                        '24740',
                        '24744'
                     ]
                  }
               ]
            }
         ]
      }
   ],
   'valid':true
}]"

Solution

  • As described, you need to add a class that handles the nested Rules objects.
    In you original class structure, the Rules class doesn't have a rules Property that can hold a second level of nesting.
    But you also need to handle an undetermined level of nesting, since other nested classes can have further nested Rules object.

    You can add a new class that handles this kind of nesting by referencing itself:

    Partial Public Class RulesList
        Public Id As String
        Public Value As Long()
        '(...)
        Public Rules As RulesList()
    End Class
    

    Plus, it must hold an array/list of Value objects.

    Note that I have used Arrays instead of Lists: it's just easier to inspect the results, you can use a List(Of [Type]) if you prefer, the final output doesn't change.


    This sample class (named Queries), implements this kind of structure.
    It also includes the Serialization and Deserialization (simplified, no error checking/handling) as static (shared) methods.

    Assume jsonInput is your JSON object:

    Deserialize to a List(Of QueryBuilder):

    Dim myQueries = Queries.Deserialize(jsonInput)
    

    Serialize a List(Of QueryBuilder) back to the original JSON object.
    Note, using the JSON visualizer in Visual Studio, that the structure is reproduced exactly as the original:

    Dim jsonOutput = Queries.Serialize(myQueries)
    

    The Queries class:

    Imports Newtonsoft.Json
    
    Public Class Queries
        Public Class QueryBuilder
            Public Condition As String
            Public Rules As Rules()
            Public Valid As Boolean
        End Class
    
        Public Class Rules
            Public Id As String
            Public Field As String
            <JsonProperty("type")>
            Public QueryType As String
            Public Input As String
            <JsonProperty("operator")>
            Public QueryOperator As String
            Public Value As String
            Public Condition As String
            Public Rules As RulesList()
        End Class
        Partial Public Class RulesList
            Public Id As String
            Public Field As String
            <JsonProperty("type")>
            Public QueryType As String
            Public Input As String
            <JsonProperty("operator")>
            Public QueryOperator As String
            Public Value As Long()
            Public Condition As String
            Public Rules As RulesList()
        End Class
    
        Public Shared Function Deserialize(jsonSource As String) As List(Of QueryBuilder)
            Return JsonConvert.DeserializeObject(Of List(Of QueryBuilder))(jsonSource)
        End Function
    
        Public Shared Function Serialize(classObject As List(Of QueryBuilder)) As String
            Return JsonConvert.SerializeObject(classObject)
        End Function
    
    End Class