落とし穴に立て札を立てるが如く

ハマりどころの解決が少しでも早くなることを願って書いていきます

MassTransit.RabbitMq 消えるデフォルト値の怪の巻

f:id:nam_yu_sql:20200216193605j:plain この記事は後ほどcloud.config TechBlogにマルチポストされます。

RabbitMq、使ってますか?
マイクロサービスアーキテクチャが流行りだしてからサービス間通信の方式として再注目され始めたメッセージキュー、そしてそのミドルウェアとなるのがRabbitMqですが、これまでもその使い方についていくつかの記事を作成してきました。
今回は、自分がそれを触っていて若干混乱した挙動について紹介したいと思います。

消えるデフォルト値の怪

C#においてクラスをシリアライズする際、通常JsonSerializerかJsonconvertを使います。
これらでクラスインスタンスjsonシリアライズする際は例えばこんなクラスがあったとして・・・

public class Test   
{   
    public bool IsTrue { get; set; }   
    public int Number { get; set; }   
}   

それをこんな風にしてやるとシリアライズできます。

var test = new Test();   
var jsonString = JsonSerializer.Serialize(test);   

このコードの出力結果は{"IsTrue":false,"Number":0}となります。

さて、RabbitMqにMassTransitを通してメッセージをやり取りする場合、メッセージはこのjsonの形でやりとりされます。
メッセージ取得の方法については以前の記事を参考していただくとして、そこでやりとりされるメッセージの内容はこのような感じです。

"message": {   
  "isTrue": true,   
  "number": 123   
},   

しかし、これがもしデフォルトの値だと・・・

"message": {},   

こうなります。
メッセージの中身が一見空白のようになってしまいます。 ここでいうデフォルトの値とは、IsTrueはfalse、Numberは0の値が入っている場合です。

はじめこのメッセージの内容を見たとき、パラメータが正常に送信されていないんじゃないかとも思いました。しかし例えばboolの値はTrueだとmessageの内容に含まれていたので、デフォルトの値はパラメータ名ごと省略して送信しているのだと気付きました。
次に心配になったのが、これをメッセージとして送信したとして、メッセージを受け取った側は正常にデシリアライズしてくれるのだろうか?ということでした。
結果から言えば、このメッセージをデシアライズすると正常にIsTrue=false、Number=0のTest型のインスタンスを生成してくれます。
なのでこのような挙動があったとしてもプログラムとしては正常に動作してくれます。
どうしてもメッセージの中身が何もないように見えるのが気になる場合、パラメータの中身がデフォルト値でもjsonには出力してもらうためにはどうすればいいかというと、手動でデフォルト値出力をするよう設定してやることで実現できます。
busの設定時にConfigureJsonSerializerでデフォルト値の扱いを設定できます。

var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>   
{   
  //  この辺りにbusのHost等の設定が入ります   
   
    sbc.ConfigureJsonSerializer(settings =>   
    {   
        settings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Include;   
        return settings;   
    });   
});   

そうするとデフォルト値も出力されるようになります。

"message": {   
  "isTrue": false,   
  "number": 0   
},   

しかし、通常はメッセージングはプロセス間でのやりとりでしか使わないのでデフォルト値は出力されない設定で問題はないと思います。
もし何らかの環境においてjsonにプロパティ名がないとデフォルト値としてもデシリアライズしてくれないということが起きた場合に改めてこの設定をするのがいいと思います。

おわりに

今回はMasstransitを用いてRabbitMqとメッセージをやり取りする際にデフォルト値はデフォルトではシリアライズされないという挙動を解説しました。
Jsonの扱いは様々な言語やフレームワークを用いる際に頻繁に取り扱うことになる分野の一つですが、その挙動の癖はしっかり把握しておきたいと思います。