はじめに
匿名型のオブジェクトをクラスのインスタンスにしたいとき、ありますよね。
こんなソースコードは嫌だ
例えば、こんなソースがあったとします。
using System;
namespace tekitou
{
class Program
{
public class DataClass
{
public string strText { get; set; }
public int numHoge { get; set; }
public override string ToString()
{
return $"{strText}, {numHoge}";
}
}
static object NanrakaFunction()
{
return new { strText = "hogehoge", numHoge = 323 };
}
static void Main(string[] args)
{
var obj = NanrakaFunction();
var fuga = (dynamic)obj as DataClass;
if (fuga == null)
{
Console.WriteLine("fuga is null");
}
else
{
Console.WriteLine(fuga);
}
}
}
}
- 「
NanrakaFunction
が staticなのヤバい」 - 「
NanrakaFunction
の 型、なんでDataClass
じゃないの?」
などなど、static object NanrakaFunction
の設計が激やばなのは認めます。
ただ、上記のソースコードほどではないとはいえ、こういう設計にならざるを得ないこともあるのではないでしょうか。
実行結果
このソースコード、実行すると当然
fuga is null
が返されます。
ではどうするか?それが今日の本題です。
解決方法
これ、バッドプラクティスな可能性がだいぶありますので、
使用する際は自己責任で。
わたし、気づきました。
Console.WriteLine(JsonSerializer.Serialize(obj));
↓
{"strText":"hogehoge","numHoge":323}
実装
static void Main(string[] args)
{
var obj = NanrakaFunction();
var strJson = JsonSerializer.Serialize(obj);
var fuga = JsonSerializer.Deserialize<DataClass>(strJson);
if (fuga == null)
{
Console.WriteLine("fuga is null");
}
else
{
Console.WriteLine(fuga);
}
}
バッドプラクティス臭がプンプンしますね!
要は一旦JSONでシリアライズできる形ならJSON文字列化してしまって、
あとでデシリアライズすればいいのです。
型チェックもちゃんとできる
例えば、 numHoge
に float型の数値をいれてみたところ・・
例外が発生しました: CLR/System.Text.Json.JsonException
型 'System.Text.Json.JsonException' のハンドルされていない例外が System.Text.Json.dll で発生しました
内部例外が見つかりました。詳細については、変数ウィンドウの $exception を参照してください。
最も内側の例外 System.FormatException : Either the JSON value is not in a supported format, or is out of bounds for an Int32.
場所 System.Text.Json.Utf8JsonReader.GetInt32()
場所 System.Text.Json.Serialization.Converters.JsonConverterInt32.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
場所 System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(ReadStack& state, Utf8JsonReader& reader)
場所 System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader)
場所 System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
いいぞ。
ちゃんとデシリアライズ時の例外をチェックすれば、型がちゃんとできてるかどうかもわかります。
終わりに
とまぁ、今回は NanrakaFunction
というかたちで、関数で定義しましたが、
引数でやってくる場合もあるわけです。(objectで受けるな、というのはあるが)
とりあえずの処置として使えるかな、ということで記事にしてみました。
変換を自前で書くほどデンジャラスなこともないと思うので、公式のライブラリに委ねてみましょう、ということでした。