"content_type"キーによって、入れ子になった部分をUser型にデシリアライズするか、Comment型にデシリアライズするかを分けたいです。
まず JSON 文字列から content_type の値を取得して、それが "user" なのか "comment" なのかを調べて、前者なら User 型に、後者なら Comment 型にデシリアライスしてはいかがですか?
"user" なのか "comment" なのかを調べる方法は以下の記事を見てください。
JSON 文字列から指定した name の value を取得
http://surferonwww.info/BlogEngine/post/2021/02/11/find-value-by-name-in-json-string.aspx
【追記】
具体例を書いておきます。
上の回答に「"user" なのか "comment" なのかを調べる方法は以下の記事を見てください」と書きましたが、質問に書いてある JSON 文字列 2 つのパターンだけで決まりであれば、もっと簡単にできますので以下にその方法を書きます。
質問の JSON 文字列は末尾の } が抜けているという間違いがありますがそこは直して、以下の 2 つのパターンだけ考えればよいと理解します。
{
"content_type": "user",
"content": {"birth": "2022-09-03","name": "panda", "age": 5}
}
{
"content_type": "comment",
"content": {"timestamp": "2022-09-05","title": "Hello", "content": "Nice to meet you"}
}
まず、2 つのパターンどちらにもデシリアライズできるクラス定義を作り、これにデシリアライズします。
public class Rootobject
{
public string? content_type { get; set; }
public Content? content { get; set; }
}
public class Content
{
public string? birth { get; set; }
public string? name { get; set; }
public int age { get; set; }
public string? timestamp { get; set; }
public string? title { get; set; }
public string? content { get; set; }
}
System.Text.Json のデシリアライザを使うと以下のようになります。
using System.Text.Json;
string jsonString1 = @"{
""content_type"": ""user"",
""content"": {""birth"": ""2022-09-03"",""name"": ""panda"", ""age"": 5}
}";
string jsonString2 = @"{
""content_type"": ""comment"",
""content"": {""timestamp"": ""2022-09-05"",""title"": ""Hello"", ""content"": ""Nice to meet you""}
}";
Rootobject? rootobject1 = JsonSerializer.Deserialize<Rootobject>(jsonString1);
Rootobject? rootobject2 = JsonSerializer.Deserialize<Rootobject>(jsonString2);
デシリアライズの結果、JSON 文字列の content の中に Content クラスのプロパティに該当するものがない場合は string? 型は null に int 型は 0 になります。
上の rootobject1, rootobject2 を質問にある Log, User, Comment クラスに詰め替えます。具体例は以下のサンプルコードを見てください。詰め替える際に content_type が "user" なのか "comment" なのかを調べて処理しています。
static Log? CreateLog(Rootobject? rootObj)
{
if (rootObj == null)
{
return null;
}
if (rootObj.content_type == "user")
{
var log = new Log()
{
content_type = rootObj.content_type,
user = new User
{
birth = ((Func<string?, DateTime>)((s) => {
DateTime dateValue;
DateTime.TryParse(s, out dateValue);
return dateValue;
}))(rootObj.content?.birth),
name = rootObj.content?.name,
age = (rootObj.content != null)? rootObj.content.age : 0
},
comment = null
};
return log;
}
else if (rootObj.content_type == "comment")
{
var log = new Log()
{
content_type = rootObj.content_type,
user = null,
comment = new Comment
{
timestamp = ((Func<string?, DateTime>)((s) => {
DateTime dateValue;
DateTime.TryParse(s, out dateValue);
return dateValue;
}))(rootObj.content?.timestamp),
title = rootObj.content?.title,
content = rootObj.content?.content
}
};
return log;
}
else
{
return null;
}
}
結果は以下のようになります。
