回答編集履歴

2

追記

2022/09/07 03:12

投稿

退会済みユーザー
test CHANGED
@@ -8,3 +8,128 @@
8
8
  JSON 文字列から指定した name の value を取得
9
9
  http://surferonwww.info/BlogEngine/post/2021/02/11/find-value-by-name-in-json-string.aspx
10
10
 
11
+ ---
12
+
13
+ **【追記】**
14
+
15
+ 具体例を書いておきます。
16
+
17
+ 上の回答に「"user" なのか "comment" なのかを調べる方法は以下の記事を見てください」と書きましたが、質問に書いてある JSON 文字列 2 つのパターンだけで決まりであれば、もっと簡単にできますので以下にその方法を書きます。
18
+
19
+ 質問の JSON 文字列は末尾の } が抜けているという間違いがありますがそこは直して、以下の 2 つのパターンだけ考えればよいと理解します。
20
+
21
+ ```
22
+ {
23
+ "content_type": "user",
24
+ "content": {"birth": "2022-09-03","name": "panda", "age": 5}
25
+ }
26
+
27
+ {
28
+ "content_type": "comment",
29
+ "content": {"timestamp": "2022-09-05","title": "Hello", "content": "Nice to meet you"}
30
+ }
31
+ ```
32
+
33
+ まず、2 つのパターンどちらにもデシリアライズできるクラス定義を作り、これにデシリアライズします。
34
+
35
+ ```
36
+ public class Rootobject
37
+ {
38
+ public string? content_type { get; set; }
39
+ public Content? content { get; set; }
40
+ }
41
+
42
+ public class Content
43
+ {
44
+ public string? birth { get; set; }
45
+ public string? name { get; set; }
46
+ public int age { get; set; }
47
+ public string? timestamp { get; set; }
48
+ public string? title { get; set; }
49
+ public string? content { get; set; }
50
+ }
51
+ ```
52
+
53
+ System.Text.Json のデシリアライザを使うと以下のようになります。
54
+
55
+ ```
56
+ using System.Text.Json;
57
+
58
+ string jsonString1 = @"{
59
+ ""content_type"": ""user"",
60
+ ""content"": {""birth"": ""2022-09-03"",""name"": ""panda"", ""age"": 5}
61
+ }";
62
+
63
+ string jsonString2 = @"{
64
+ ""content_type"": ""comment"",
65
+ ""content"": {""timestamp"": ""2022-09-05"",""title"": ""Hello"", ""content"": ""Nice to meet you""}
66
+ }";
67
+
68
+ Rootobject? rootobject1 = JsonSerializer.Deserialize<Rootobject>(jsonString1);
69
+ Rootobject? rootobject2 = JsonSerializer.Deserialize<Rootobject>(jsonString2);
70
+ ```
71
+
72
+ デシリアライズの結果、JSON 文字列の content の中に Content クラスのプロパティに該当するものがない場合は string? 型は null に int 型は 0 になります。
73
+
74
+
75
+ 上の rootobject1, rootobject2 を質問にある Log, User, Comment クラスに詰め替えます。具体例は以下のサンプルコードを見てください。詰め替える際に content_type が "user" なのか "comment" なのかを調べて処理しています。
76
+
77
+
78
+ ```
79
+ static Log? CreateLog(Rootobject? rootObj)
80
+ {
81
+ if (rootObj == null)
82
+ {
83
+ return null;
84
+ }
85
+
86
+ if (rootObj.content_type == "user")
87
+ {
88
+ var log = new Log()
89
+ {
90
+ content_type = rootObj.content_type,
91
+ user = new User
92
+ {
93
+ birth = ((Func<string?, DateTime>)((s) => {
94
+ DateTime dateValue;
95
+ DateTime.TryParse(s, out dateValue);
96
+ return dateValue;
97
+ }))(rootObj.content?.birth),
98
+ name = rootObj.content?.name,
99
+ age = (rootObj.content != null)? rootObj.content.age : 0
100
+ },
101
+ comment = null
102
+ };
103
+
104
+ return log;
105
+ }
106
+ else if (rootObj.content_type == "comment")
107
+ {
108
+ var log = new Log()
109
+ {
110
+ content_type = rootObj.content_type,
111
+ user = null,
112
+ comment = new Comment
113
+ {
114
+ timestamp = ((Func<string?, DateTime>)((s) => {
115
+ DateTime dateValue;
116
+ DateTime.TryParse(s, out dateValue);
117
+ return dateValue;
118
+ }))(rootObj.content?.timestamp),
119
+ title = rootObj.content?.title,
120
+ content = rootObj.content?.content
121
+ }
122
+ };
123
+
124
+ return log;
125
+ }
126
+ else
127
+ {
128
+ return null;
129
+ }
130
+ }
131
+ ```
132
+
133
+ 結果は以下のようになります。
134
+
135
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-09-07/b8a7e8d0-7a26-4e64-8b3e-6e3d5ae2d7f2.jpeg)

1

誤字訂正

2022/09/06 09:27

投稿

退会済みユーザー
test CHANGED
@@ -1,6 +1,6 @@
1
1
  > "content_type"キーによって、入れ子になった部分をUser型にデシリアライズするか、Comment型にデシリアライズするかを分けたいです。
2
2
 
3
- まず JSON 文字列から content_type の値を取得して、それが "user" なのか "comment" なのかを調べて、前者なら User 型に、後者なら Comment 型にデシリアライスしてはいかがでか?
3
+ まず JSON 文字列から content_type の値を取得して、それが "user" なのか "comment" なのかを調べて、前者なら User 型に、後者なら Comment 型にデシリアライスしてはいかがでか?
4
4
 
5
5
 
6
6
  "user" なのか "comment" なのかを調べる方法は以下の記事を見てください。