😒
C#: 匿名型とValueTupleではシリアライズ結果が違う
入力例
匿名型
var rect1 = new
{
left = 1,
top = 2,
right = 3,
bottom = 4,
};
ValueTuple
var rect2 =
(
left: 1,
top: 2,
right: 3,
bottom: 4
);
MessagePack-CSharp
MessagePack-CSharp 2.3.85 を使用してMessagePack形式にする場合、以下のような差になります。
using MessagePack;
var msgpack1 = MessagePackSerializer.Serialize(rect1);
var msgpack2 = MessagePackSerializer.Serialize(rect2);
Console.WriteLine(MessagePackSerializer.ConvertToJson(msgpack1));
Console.WriteLine(MessagePackSerializer.ConvertToJson(msgpack2));
{"left":1,"top":2,"right":3,"bottom":4}
[1,2,3,4]
Json.NET
Json.NET (Newtonsoft.Json) 13.0.1 を使用した場合は以下の通りでした。
using Newtonsoft.Json;
Console.WriteLine(JsonConvert.SerializeObject(rect1));
Console.WriteLine(JsonConvert.SerializeObject(rect2));
{"left":1,"top":2,"right":3,"bottom":4}
{"Item1":1,"Item2":2,"Item3":3,"Item4":4}
System.Text.Json
.NET 5にてSystem.Text.Json を使用した場合は以下の通りでした。
using System.Text.Json;
Console.WriteLine(JsonSerializer.Serialize(rect1));
Console.WriteLine(JsonSerializer.Serialize(rect2));
{"left":1,"top":2,"right":3,"bottom":4}
{}
まとめ
あるモデルの値をリテラルのみによってC#ソースコード中に書きたいと思ったとき、昔からある匿名型に加え、最近ValueTupleによる記法もでき、この2択になりました。ただし、両者はC#における触り心地はそれほど大差なくても、シリアライズすると結構差がありました。概ね、匿名型の方が芳しい結果に思えます。
おことわり
各種オプションはあまり調べておらず、各ライブラリで最も素朴な使い方のみ試しています。別な結果にできる可能性はあります。
コード
.NET Fiddleですぐ動作も確認できます。https://dotnetfiddle.net/g2UtPA
Discussion
System.Text.JsonでValueTupleがシリアライズされないのは、中の値がフィールドだからです。
これは
IncludeFields
を指定することで回避できます。