With Json.NET - Newtonsoft I have successfully used custom contract deserializers and json converter to select the deserializer based on a tag (in the case below ev).
In summary I am looking to achieve the same with Utf8Json, full details below:
// Stocks TRADE:
{
"ev": "T", // Event Type
"sym": "MSFT", // Symbol Ticker
"x": "4", // Exchange ID
"i": 12345, // Trade ID
"z": 3, // Tape ( 1=A 2=B 3=C)
"p": 114.125, // Price
"s": 100, // Trade Size
"c": [0, 12], // Trade Conditions
"t": 1536036818784 // Trade Timestamp ( Unix MS )
}
// Stocks QUOTE:
{
"ev": "Q", // Event Type
"sym": "MSFT", // Symbol Ticker
"bx": "4", // Bix Exchange ID
"bp": 114.125, // Bid Price
"bs": 100, // Bid Size
"ax": "7", // Ask Exchange ID
"ap": 114.128, // Ask Price
"as": 160, // Ask Size
"c": 0, // Quote Condition
"t": 1536036818784 // Quote Timestamp ( Unix MS )
}
// Stocks Aggregate:
{
"ev": "AM", // Event Type ( A = Second Agg, AM = Minute Agg )
"sym": "MSFT", // Symbol Ticker
"v": 10204, // Tick Volume
"av": 200304, // Accumulated Volume ( Today )
"op": 114.04, // Todays official opening price
"vw": 114.4040, // VWAP (Volume Weighted Average Price)
"o": 114.11, // Tick Open Price
"c": 114.14, // Tick Close Price
"h": 114.19, // Tick High Price
"l": 114.09, // Tick Low Price
"a": 114.1314, // Tick Average / VWAP Price
"s": 1536036818784, // Tick Start Timestamp ( Unix MS )
"e": 1536036818784, // Tick End Timestamp ( Unix MS )
}
And a text stream that can consist of any of the above types:
[{"ev":"A","sym":"DAL","v":1,"av":1, ...snipped...},{"ev":"T","sym":"MSFT","p":114.11,"x":"4","s":67,"t":1586418423607, ...snipped... }]
And deserialize to:
class Message
{
List<Trade> Trades { get; set; }
List<Quote> Quotes { get; set; }
List<Aggregate> Aggs { get; set; }
}
I am currently doing this, which works, but doubt is as performant as direct deserialization into POCO:
var array = JsonSerializer.Deserialize<dynamic>(@"[{""ev"":""A"",""sym"":""AAL"",""v"":1500,""av"":119037385,""op"":12.64,""vw"":13.1,""o"":13.1,""c"":13.1,""h"":13.1,""l"":13.1,""a"":12.6655,""z"":500,""s"":1586472438000,""e"":1586472439000},{""ev"":""A"",""sym"":""AAL"",""v"":6000,""av"":119043385,""op"":12.64,""vw"":13.1,""o"":13.1,""c"":13.1,""h"":13.1,""l"":13.1,""a"":12.6655,""z"":1000,""s"":1586472439000,""e"":1586472440000},{""ev"":""A"",""sym"":""AAL"",""v"":3000,""av"":119046385,""op"":12.64,""vw"":13.11,""o"":13.11,""c"":13.11,""h"":13.11,""l"":13.11,""a"":12.6655,""z"":1000,""s"":1586472440000,""e"":1586472441000}]");
foreach(var item in array)
{
if(item["ev"]=="A")
{
var aggregate = new OpenHighLowClose(
DateTimeOffset.FromUnixTimeMilliseconds((long)item["s"]),
(decimal)item["op"],
(decimal)item["h"],
(decimal)item["l"],
(decimal)item["c"],
(decimal)item["v"]);
}
else if(item["ev"=="AM"]) { }
else if(item["ev" == "T"]) { }
else if(item["ev" == "Q"]) { }
}
What is the equivalent of json.net's JsonConverter in Utf8Json, so I can switch the deserializer based on the EV field (and associated string value of either T, A, AM or Q)?
Just to add, i am going from JSON to and want to OpenHighLowClose POCO which I will then send out via message pack... is there any way to skip this intermediate step?
If you can assume that the
evfield always comes first in an object, it's possible to get away with minimum allocations and minimum extra parsing. In netcoreapp3.0 and later,System.Text.Jsonsupports custom type converters, and one can write code like this:If for some reason you can't use netcoreapp3.x, then you will have to forgo
JsonSerializerfor the outerMessageand run the code in theReadmethod directly. If you are willing to spend a bit of cycles to avoid deserializing the inner objects manually, then applyJsonPropertyNameattributes on your property namesand rewrite the outer loop of the
Readmethod like this: