Exception while parsing Json

Mattia Fanti 356 Reputation points
2022-03-03T14:11:12.66+00:00

Hi, I'm parsin a Json API

which is basically an API from one crypto coin of a crypto exchange. Now the crypto coin is under maintenance, so the trading is closed and the Json is changed.
The JSON when the trading coin is open is:

{"error":null,"result":{"KIBAUSDT":{"limit":100,"offset":0,"total":1,"records":[{"user":2996434,"id":82651361103,"market":"KIBAUSDT","freeze":"0.001","fee_stock":"","source":"web","type":1,"side":2,"ctime":1645022087.403207,"mtime":1645022087.403207,"price":"0.00001","amount":"100","taker_fee":"0.0035","maker_fee":"-0.003","left":"100","deal_stock":"0","deal_money":"0","deal_fee":"0","alt_fee":"0","deal_fee_alt":"0","status":0}]}},"id":305636871}

While now that the trading is in maintenance, the Json is:

{"error":{"code":6,"message":"RET_TRADE_NOT_OPENKIBAUSDT"},"result":null,"id":0}

The code I was using in order to parse the JSON when the trading is open is:

Option Strict On
Imports System
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Converters
Imports System.Runtime.CompilerServices

Namespace OrdiniAperti
    Partial Public Class Openorders
        <JsonProperty("error")>
        Public Property [Error] As Object
        <JsonProperty("result")>
        Public Property Result As Result
        <JsonProperty("id")>
        Public Property Id As Double
    End Class

    Partial Public Class Result
        <JsonProperty("KIBAUSDT")>
        Public Property Kibausdt As Kibausdt
    End Class

    Partial Public Class Kibausdt
        <JsonProperty("limit")>
        Public Property Limit As Double
        <JsonProperty("offset")>
        Public Property Offset As Double
        <JsonProperty("total")>
        Public Property Total As Double
        <JsonProperty("records")>
        Public Property Records As Record()
    End Class

    Partial Public Class Record
        <JsonProperty("user")>
        Public Property User As Double
        <JsonProperty("id")>
        Public Property Id As Double
        <JsonProperty("market")>
        Public Property Market As String
        <JsonProperty("freeze")>
        Public Property Freeze As String
        <JsonProperty("fee_stock")>
        Public Property FeeStock As String
        <JsonProperty("source")>
        Public Property Source As String
        <JsonProperty("type")>
        Public Property Type As Double
        <JsonProperty("side")>
        Public Property Side As Double
        <JsonProperty("ctime")>
        Public Property Ctime As Double
        <JsonProperty("mtime")>
        Public Property Mtime As Double
        <JsonProperty("price")>
        Public Property Price As String
        <JsonProperty("amount")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property Amount As Double
        <JsonProperty("taker_fee")>
        Public Property TakerFee As String
        <JsonProperty("maker_fee")>
        Public Property MakerFee As String
        <JsonProperty("left")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property Left As Double
        <JsonProperty("deal_stock")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property DealStock As Double
        <JsonProperty("deal_money")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property DealMoney As Double
        <JsonProperty("deal_fee")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property DealFee As Double
        <JsonProperty("alt_fee")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property AltFee As Double
        <JsonProperty("deal_fee_alt")>
        <JsonConverter(GetType(ParseStringConverter))>
        Public Property DealFeeAlt As Double
        <JsonProperty("status")>
        Public Property Status As Double
    End Class

    Partial Public Class Openorders
        Public Shared Function FromJson(ByVal json As String) As Openorders
            Return JsonConvert.DeserializeObject(Of Openorders)(json, Settings)
        End Function
    End Class

    Public Module Serialize
        <Extension()>
        Public Function ToJson(ByVal self As Openorders) As String
            Return JsonConvert.SerializeObject(self, Settings)
        End Function
    End Module

    Friend Module Converter
        Public ReadOnly Settings As JsonSerializerSettings = New JsonSerializerSettings With {
            .MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            .DateParseHandling = DateParseHandling.None
}
        'System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture

    End Module

    Friend Class ParseStringConverter
        Inherits JsonConverter

        Public Overrides Function CanConvert(ByVal t As Type) As Boolean
            Return t Is GetType(Double) OrElse t Is GetType(Double?)
        End Function

        Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
            If reader.TokenType = JsonToken.Null Then Return Nothing
            Dim value = serializer.Deserialize(Of String)(reader)
            Dim l As Double

            If Double.TryParse(value, l) Then
                Return l
            End If

            Throw New Exception("Cannot unmarshal type Double")
        End Function

        Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
            If untypedValue Is Nothing Then
                serializer.Serialize(writer, Nothing)
                Return
            End If

            Dim value = CLng(untypedValue)
            serializer.Serialize(writer, value.ToString())
            Return
        End Sub

        Public Shared ReadOnly Singleton As ParseStringConverter = New ParseStringConverter()
    End Class
End Namespace

and in a button:

 Dim json = Await wc1.DownloadStringTaskAsync(TextBox1.Text)
                'deserialize the json
                Dim rootObj = Openorders.FromJson(json)
                'navigate to Kibausdt ( when trading is open)
                Dim kibausdt = rootObj.Result.Kibausdt
                'navigate to Id ( when trade is closed)
                Dim opentrading = rootObj.Id

                If opentrading = 0 Then
                    RichTextBox3.Text = "trading not open"
                Else
                    If kibausdt.Total = 0 Then
                        RichTextBox3.Text = "0 opened orders"

                    Else
                        RichTextBox3.Clear()
                        'loop through records
                        For Each record In kibausdt.Records
                            Dim side As String = record.Side.ToString()
ecc

So as you can see from the code in the button, I'm trying to navigate to Id because id become to 0 when the trading is not open. But unfortunately I'm getting an error at debug, the app goes in break mode and it thrown the following error : System.Reflection.TargetInvocationException: 'exception has been thrown by the target of an invocation
How it is possible? I'm navigate correctly to the Id, so I'm excpeting it to work..
Any idea?
Thanks

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,605 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Jiachen Li-MSFT 27,241 Reputation points Microsoft Vendor
    2022-03-04T01:46:39.113+00:00

    Hi @Mattia Fanti ,
    When the trading is not open, Result is null.
    So Dim kibausdt = rootObj.Result.Kibausdt will throw an exception.
    You can first judge whether the trading is open by error or id, and then perform other operations.
    Best Regards.
    Jiachen Li

    ----------

    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Jose Zero 576 Reputation points
    2022-03-05T16:53:08.4+00:00

    Here same logic applied to part of your code, attention to logic,
    Sounds obvious, but you can't ask for a children property when parent does not exist, as I know there is no other way other than follow class tree structure and check for null before go further
    Just in case check for "error" or "id" can be considered a personal preference, personally I preffer deal with "error" it can give some additional info you might need in future

    Dim json = Await wc1.DownloadStringTaskAsync(TextBox1.Text)
        Dim MyData As Openorders = Openorders.FromJson(json)
        If MyData.error IsNot Nothing Then
          RichTextBox3.Text = "Oops, there is an error."
          If MyData.id = 0 Then
            RichTextBox3.Text = RichTextBox3.Text & vbCrLf & "and trading not open"
          End If
        Else
          If MyData.result IsNot Nothing Then
            If MyData.result.KIBAUSDT IsNot Nothing Then
              If MyData.result.KIBAUSDT.total = 0 Then
                RichTextBox3.Text = "0 opened orders"
              Else
                RichTextBox3.Clear()
                For Each record In MyData.result.KIBAUSDT.records
                  Dim side As String = record.side.ToString()
                Next
              End If
            Else
              RichTextBox3.Text = "there is no KIBAUSDT"
            End If
          Else
            RichTextBox3.Text = "there is no result"
          End If
        End If