How to dynamically parse JSON representation of a nested object

I store asynchronous messages from RabbitMQ in a MongoDB as string using <MyObject>.ToJson(). If something goes wrong, my error message handler can get a JSON representation of the original message sent. However the error handling does not have any type information.

So I try to dynamically parse the stored JSON representation using Json.Parse(<string from database>) and try to extract those props I need for further processing. The first level works fine, but if a property represents another object, the keys are strange… Here is the JSON representation as shown in my IDE:

{
  "upsertMsgDto":{
    "invoice":{
      "invoiceDate":1557826179129,
      "invoiceDueDate":1560418179129,
      "customerNumber":"2019-3211069506",
      "paymentTermCode":"30T",
      "invoiceNumber":"R-2019-2088053278",
      "invoiceTotal":524.1396,
      "payMethodName":"Manuell-CHF",
      "invoiceText":"Invoice 'R-2019-2088053278' for WineBar Stäfa (2019-3211069506),
       Stäfa from 2019-05-14",
      "payslipCode":"931113000000201920880532787",
      "invoicePositions":[
        {
          "postingAccountNumber":"1100",
          "amountExVat":524.1396,
          "vatAmount":0,
          "isDebit":true,
          "isInclusive":true,
          "postingText":"Invoice number 'R-2019-2088053278' from 2019-05-14 for customer WineBar Stäfa,
           8712 Stäfa"
        },
        {
          "postingAccountNumber":"3200",
          "amountExVat":139.27576601671308,
          "vatAmount":10.724233983286908,
          "vatCode":"UStn",
          "isDebit":false,
          "isInclusive":true,
          "postingText":"Invoice 'R-2019-2088053278' for 'WineBar Stäfa',
           6 Flasche Rivetto,
           Piemont"
        },
        {
          "postingAccountNumber":"3200",
          "amountExVat":132.59052924791087,
          "vatAmount":10.209470752089137,
          "vatCode":"UStn",
          "isDebit":false,
          "isInclusive":true,
          "postingText":"Invoice 'R-2019-2088053278' for 'WineBar Stäfa',
           6 Flasche Cascina Adelaide,
           Piemont"
        },
        {
          "postingAccountNumber":"3200",
          "amountExVat":214.8,
          "vatAmount":16.5396,
          "vatCode":"UStn",
          "isDebit":false,
          "isInclusive":false,
          "postingText":"Invoice 'R-2019-2088053278' for 'WineBar Stäfa',
           12 Flasche Salzl Chardonnay 2017"
        }
      ]
    },
    "tenantGuid":"46c70827-e6e8-4ebc-b99c-f0c57d4e025d"
  },
  "commandCreator":"batwo",
  "messageId":"26a8c46d-94d4-4936-b5db-c275a1323dec",
  "publisherId":"pubsub-bbde"
}

According to JSONLint this JSON is valid.
To parse this I do the following in C#:
Step 1: Get the keys from the original message object.

var origMsg = JsonObject.Parse(msgProtEntry.MessageJson);
Console.WriteLine($"Printing message properties:");
foreach (var key in origMsg.Keys)
{
	Console.WriteLine($"Message-Key: {key}");
}

The output of the keys looks good:

Message-Key: upsertMsgDto
Message-Key: commandCreator
Message-Key: messageId
Message-Key: publisherId

Now I try to parse the value of the key upsertMsgDto like so:

// Parsing the invoice message DTO
var upsertMsgDto = JsonObject.Parse(origMsg["upsertMsgDto"]);
Console.WriteLine($"Printing upsertMsgDto properties:");
foreach (var key in upsertMsgDto.Keys)
{
	Console.WriteLine($"Key: {key}");
}

And the result is strange and looks like the value contains incorrect JSON data:

Printing upsertMsgDto properties:
Key: invoice:{invoiceDate:1557826179129
Key: customerNumber:2019-3211069506
Key: invoiceNumber:R-2019-2088053278
Key: payMethodName:Manuell-CHF
Key: 'R-2019-2088053278'
Key: WineBar
Key: (2019-3211069506)
Key: from
Key: payslipCode:931113000000201920880532787
Key: amountExVat:524.13960000000000000000000000
Key: isDebit:true
Key: postingText:Invoice
Key: 2019-05-14
Key: customer
Key: Stäfa
Key: Stäfa}
Key: {postingAccountNumber:3200
Key: vatAmount:10.209470752089136490250696379
Key: isDebit:false
Key: for
Key: Stäfa'
Key: Flasche
Key: Adelaide
Key: ]}

Correctly it should return two keys:

  • invoice
  • tenantGuid

Where invoice is another complex object.

So it looks like I am on the wrong path here! How can I correctly dynamically parse such nested objects?

JsonObject is a wrapper around Dictionary<string,string> that requires you to manually traverse the JSON structure to fetch the data you want.

If you want to parse adhoc JSON into C# data structure you can use #Script JSON.parse() which also preserves the JSON data type, e.g. bool, int, and double values.

Ahh, got it. Works now as expected.

I will definitely look into #Script in more detail since I see some use cases it could be VERY helpful for me. But to extract two or three properties in an error handler, it is a bit an overkill to load the entire engine…

Thanks for your help and hint!