Utf8Jsonでの、ダブルクオーテーション付き数値への対応方法

仮想通貨のシステムトレードをやろうとすると、避けて通れないのがJSON。
WebAPIではJSONで結果が返ってくる場合がものすごく多いです。

そして、システムトレードは、速度が売買の成立や損益にものすごく影響があります。
1ミリ秒でも早く処理したい。
私はC#でプログラムを書くので、そこでお世話になるのが、Utf8Jsonです。
河合さん、いつもお世話になっております。

さて、Utf8Jsonが速いのはありがたいのですが、プログラムを書いていくといろいろ困ることにもぶつかるわけでして、その対策とかも書いていこうと思います。

・価格と数量が、ダブルクォーテーションで囲まれてくる。
いくつかのマーケットでは、価格や数量の情報が、ダブルクォーテーションで囲まれてやってきます。
[[“4560000″,”0.01”],[…みたいな感じです。
JSONの定義では、数値はダブルクォーテーションでは囲わないルールなのに、なぜでしょうかねぇ。
「価格や数量は、文字です。数値ではありません。」って事なんでしょうか。なんでやねん。

まあ、ダブルクオーテーションで囲われた数値がやってくる現実がここにあるので、なにはともあれ対応するしかありません。
stringにデシリアライズして、Convert.ToDoubleで数値にすれば、解決です。
ええ、確かに動きますが、Uft8をUtf16にし、そこからdoubleに・・・。
せっかくUtf8Jsonがスピード出してくれるのに台無しな感じですね。
直接doubleとして、Utf8Jsonで変換しようとすると、当然エラーが起きます。

私の対処方としては、以下を採用しました。

public class Item
{
    public List<List<QuotedDoubleStruct>> bids { get; set; }
    public List<List<QuotedDoubleStruct>> asks { get; set; }
}

[JsonFormatter(typeof(QuotedDoubleStructFormatter))]
public struct QuotedDoubleStruct
{
    public QuotedDoubleStruct(double value)
    {
        this.Value = value;
    }

    public double Value { get; set; }
}

public class QuotedDoubleStructFormatter : IJsonFormatter<QuotedDoubleStruct>
{
    public static readonly QuotedDoubleStructFormatter Default = new QuotedDoubleStructFormatter();

    public void Serialize(ref JsonWriter writer, QuotedDoubleStruct value, IJsonFormatterResolver formatterResolver)
    {
        writer.WriteQuotedDouble(value.Value);
    }

    public QuotedDoubleStruct Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
    {
        return new QuotedDoubleStruct(reader.ReadQuotedDouble());
    }
}

public static class JsonWriterExtensions
{
    public static void WriteQuotedDouble(ref this JsonWriter writer, double value)
    {
        writer.WriteQuotation();
        writer.WriteDouble(value);
        writer.WriteQuotation();
    }
}

public static class JsonReaderExtensions
{
    public static double ReadQuotedDouble(ref this JsonReader reader)
    {
        reader.SkipWhiteSpace();
        reader.AdvanceOffset(1);
        double value = reader.ReadDouble();
        reader.AdvanceOffset(1);
        return value;
    }
}

エラーチェックとかは足りてないので、想定外のJSONが来て困るかもしれませんが、とりあえず問題はなさそうです。
もっと良い方法や、別の方法をお持ちの方は、教えていただけるとうれしいです。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です