Home > Mobile >  JsonDocument API throws an exception "The requested operation requires an element of type '
JsonDocument API throws an exception "The requested operation requires an element of type '

Time:06-19

JsonDocument.Parse throws The requested operation requires an element of type 'Object', but the target element has type 'Array'., because the message is actually an array. You can see that in the log below.

How can I deal with it?

My code:

private void OnMessageReceived(object? sender, MessageReceivedEventArgs e)
{
    _logger.LogTrace("Message was received. {Message}", Encoding.UTF8.GetString(e.Message.Buffer.Span));

    using var document = JsonDocument.Parse(e.Message.Buffer);

    if (document.RootElement.TryGetProperty("reqid", out var requestIdElement))
    {
        _logger.LogInformation("REQID");
    }
}

My log, which includes the JSON:

[15:17:02 VRB] Connection task started: wss://ws.kraken.com
[15:17:02 VRB] Connecting...
[15:17:09 VRB] OnConnected: Connection opened (URL: wss://ws.kraken.com)
[15:17:09 VRB] Message was received. {"connectionID":8059679396249595639,"event":"systemStatus","status":"online","version":"1.9.0"}
[15:17:09 VRB] Message was received. {"channelID":340,"channelName":"ticker","event":"subscriptionStatus","pair":"XBT/USD","reqid":1,"status":"subscribed","subscription":{"name":"ticker"}}
[15:17:09 INF] REQID
[15:17:09 VRB] Message was received. {"channelID":356,"channelName":"ticker","event":"subscriptionStatus","pair":"XBT/EUR","reqid":1,"status":"subscribed","subscription":{"name":"ticker"}}
[15:17:09 INF] REQID
[15:17:09 VRB] Message was received. [340,{"a":["19183.10000",11,"11.73924682"],"b":["19183.00000",0,"0.00700000"],"c":["19189.90000","0.00001057"],"v":["5483.17940238","8791.76237363"],"p":["19447.36865","19869.35727"],"t":[25966,42418],"l":["18728.00000","18728.00000"],"h":["20740.10000","20995.20000"],"o":["20440.30000","20988.50000"]},"ticker","XBT/USD"]
[15:17:09 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:09 VRB] Message was received. [356,{"a":["18300.10000",6,"6.96418059"],"b":["18300.00000",0,"0.00830972"],"c":["18300.10000","0.00010000"],"v":["2542.62440365","3607.51107542"],"p":["18436.15535","18790.67960"],"t":[32790,49726],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:09 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:10 VRB] Message was received. {"event":"heartbeat"}
[15:17:10 VRB] Message was received. [356,{"a":["18300.10000",6,"6.96418059"],"b":["18281.10000",0,"0.00566993"],"c":["18281.10000","0.06940181"],"v":["2542.72440365","3607.61107542"],"p":["18436.14941","18790.66558"],"t":[32794,49730],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:10 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:10 VRB] Message was received. [340,{"a":["19183.10000",18,"18.23619321"],"b":["19183.00000",0,"0.01700000"],"c":["19183.10000","0.00052110"],"v":["5483.17992348","8791.76289473"],"p":["19447.36863","19869.35723"],"t":[25967,42419],"l":["18728.00000","18728.00000"],"h":["20740.10000","20995.20000"],"o":["20440.30000","20988.50000"]},"ticker","XBT/USD"]
[15:17:10 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:11 VRB] Message was received. {"event":"heartbeat"}
[15:17:11 VRB] Message was received. [356,{"a":["18284.20000",0,"0.02704155"],"b":["18281.20000",0,"0.03883245"],"c":["18284.20000","0.00027995"],"v":["2542.72468360","3607.61135537"],"p":["18436.14939","18790.66554"],"t":[32795,49731],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:11 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:11 VRB] Message was received. [356,{"a":["18283.00000",1,"1.30361502"],"b":["18281.20000",0,"0.03883245"],"c":["18283.00000","0.00060000"],"v":["2542.72528360","3607.61145187"],"p":["18436.14936","18790.66529"],"t":[32796,49730],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:11 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:11 VRB] Message was received. [340,{"a":["19183.10000",18,"18.48100120"],"b":["19178.00000",0,"0.00010000"],"c":["19183.00000","0.01000000"],"v":["5483.19692348","8791.77989473"],"p":["19447.36781","19869.35590"],"t":[25969,42421],"l":["18728.00000","18728.00000"],"h":["20740.10000","20995.20000"],"o":["20440.30000","20988.50000"]},"ticker","XBT/USD"]
[15:17:11 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:12 VRB] Message was received. {"event":"heartbeat"}
[15:17:13 VRB] Message was received. {"event":"heartbeat"}
[15:17:13 VRB] Message was received. [356,{"a":["18281.40000",0,"0.36978062"],"b":["18280.90000",0,"0.00059082"],"c":["18281.40000","0.05021938"],"v":["2542.77550298","3607.66167125"],"p":["18436.14630","18790.65820"],"t":[32797,49731],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:13 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:13 VRB] Message was received. [340,{"a":["19178.10000",13,"13.16759732"],"b":["19173.70000",0,"0.07544241"],"c":["19178.00000","0.00010000"],"v":["5483.19702348","8791.72817814"],"p":["19447.36780","19869.34930"],"t":[25970,42419],"l":["18728.00000","18728.00000"],"h":["20740.10000","20995.20000"],"o":["20440.30000","20989.60000"]},"ticker","XBT/USD"]
[15:17:13 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.
[15:17:14 VRB] Message was received. {"event":"heartbeat"}
[15:17:14 VRB] Message was received. [356,{"a":["18280.90000",1,"1.09763896"],"b":["18280.80000",0,"0.05424140"],"c":["18280.90000","0.00236104"],"v":["2542.77786402","3607.66403229"],"p":["18436.14616","18790.65786"],"t":[32798,49732],"l":["17905.00000","17905.00000"],"h":["19765.20000","20030.50000"],"o":["19482.40000","20030.50000"]},"ticker","XBT/EUR"]
[15:17:14 ERR] Data loop: The requested operation requires an element of type 'Object', but the target element has type 'Array'.

I found this thread on SO talking about JsonArray? array = JsonNode.Parse(stream)?.AsArray();. The issue is that it requires a stream. The websocket client library I'm using, returns ReadOnlyMemory<byte> only (e.Message.Buffer = ReadOnlyMemory<byte>).

CodePudding user response:

Your problem is not with JsonDocument.Parse(e.Message.Buffer), it's with the next line:

if (document.RootElement.TryGetProperty("reqid", out var requestIdElement))

As explained in the documentation for JsonElement.TryGetProperty(), if the element is a JSON array rather than a JSON object, this method will throw the exception you see:

Exceptions

InvalidOperationException
This value's ValueKind is not Object.

And in fact, your root JSON value is sometimes an object:

{"connectionID":8059679396249595639,"event":"systemStatus","status":"online","version":"1.9.0"}

But sometimes an array, causing your exception:

[340,{"a":["19183.10000",11,"11.73924682"],"b":["19183.00000",0,"0.00700000"],"c":["19189.90000","0.00001057"],"v":["5483.17940238","8791.76237363"],"p":["19447.36865","19869.35727"],"t":[25966,42418],"l":["18728.00000","18728.00000"],"h":["20740.10000","20995.20000"],"o":["20440.30000","20988.50000"]},"ticker","XBT/USD"]

Since it seems you want to log "reqid" only if present, you may check document.RootElement.ValueKind == JsonValueKind.Object before calling TryGetProperty() like so:

if (document.RootElement.ValueKind  == JsonValueKind.Object && document.RootElement.TryGetProperty("reqid", out var requestIdElement))
{
    _logger.LogInformation("REQID");
}           

You also wrote,

I found this thread on SO talking about JsonArray? array = JsonNode.Parse(stream)?.AsArray();. The issue is that it requires a stream. The websocket client library I'm using, returns ReadOnlyMemory<byte> only (e.Message.Buffer = ReadOnlyMemory<byte>).

There is an overload JsonNode.Parse(ReadOnlySpan<Byte>, Nullable<JsonNodeOptions>, JsonDocumentOptions), however switching to the JsonNode API is independent of your actual problem, which is that you must test that the incoming JSON is actually an object before attempting to fetch a property value.

  • Related