我有以下JSON(从web套接字接收到的字节[])。
{
"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, 1], // Trade Conditions
"t": 1536036818784 // Trade Timestamp ( Unix MS )
}
和一个结构体
struct Trade
{
[JsonPropertyName("sym")]
public string Symbol { get; set; }
[JsonPropertyName("p")]
public decimal Price { get; set; }
...
}
目前,我正在从JSON到结构化(使用令人惊叹的... Utf8Json
lib),然后从结构到 bytes[]
.
我希望直接从JSON到 MessagePack
序列化字节对象--因为中间的步骤似乎有点多余。
如何在保持上述属性映射的情况下实现这个目标?
理想情况下,由于我以字节[]的形式接收JSON,我想直接使用字节(而不是编码为字符串--或者如果必须这样做,至少编码不会增加很多开销)。
如果使用属性(用于JSON映射)可以让事情变得更简单的话,我是可以接受的。
我目前正在考虑的是 MessagePackWriter
到一个原始缓冲区(如果我需要使用 MemoryManager
或者干脆自己做 byte[]
数组等)。)
我的想法是在解码时直接写流,并消除了 Trade
结构。
private void GetTrade(ref Utf8JsonReader reader, IBufferWriter<byte> bufferWriter)
{
var trade = new Trade
{
TradeConditions = new int[] { }
};
// working how to use writer out :)
var writer = new MessagePackWriter(bufferWriter);
while (Expect(ref reader, JsonTokenType.PropertyName, JsonTokenType.EndObject))
{
var property = reader.GetString();
switch (property)
{
default:
this.logger.LogError($"decoding {trade.GetType().Name} found unexpected property {property}, skipping");
reader.Skip();
break;
case StreamFieldNames.Symbol:
trade.Symbol = ExpectString(ref reader, StreamFieldNames.Symbol);
break;
case StreamFieldNames.ExchangeId:
trade.ExchangeId = ExpectInt(ref reader, StreamFieldNames.ExchangeId);
break;
case StreamFieldNames.TradeId:
trade.TradeId = ExpectString(ref reader, StreamFieldNames.TradeId);
break;
case StreamFieldNames.Tape:
trade.Tape = ExpectInt(ref reader, StreamFieldNames.Tape);
break;
case StreamFieldNames.Price:
trade.Price = ExpectDecimal(ref reader, StreamFieldNames.Price);
break;
case StreamFieldNames.TradeSize:
trade.TradeSize = ExpectDecimal(ref reader, StreamFieldNames.TradeSize);
break;
case StreamFieldNames.TradeConditions:
trade.TradeConditions = ExpectIntArray(ref reader, StreamFieldNames.TradeConditions);
break;
case StreamFieldNames.Timestamp:
trade.Timestamp = ExpectUnixTimeMilliseconds(ref reader, StreamFieldNames.Timestamp);
break;
}
}
return trade;
}
如果我理解正确的话,你得到的是字节[],并且想在不将字节[]转换为字符串的情况下得到交易结构?在这种情况下,你可以使用 元帅 库来将非托管对象转换为托管对象。
public T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
T result;
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
return result;
}
你需要加入 System.Runtime.InteropServices
来实现这个功能。在这种情况下,byte[]将必须包含结构中所有声明的字段,所以你不需要任何属性。你可以在 代码工程 网站是如何工作的。虽然这个问题在C或C++中很容易解决,但在C#中,我们没有指针,这为我们减轻了生活的压力,但也删除了一些功能。