teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

9

intにはならない、bool忘れ

2021/04/16 11:29

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -94,7 +94,7 @@
94
94
  hogesの型をinterface{}にすれば任意のJSONのパースは完了します。
95
95
  以下のように型スイッチを再帰的に組むことで各値にアクセスできます。
96
96
 
97
- [https://play.golang.org/p/kbOCT3qMj3B](https://play.golang.org/p/kbOCT3qMj3B)
97
+ [https://play.golang.org/p/MFEcaerWzlP](https://play.golang.org/p/MFEcaerWzlP)
98
98
  ```go
99
99
  package main
100
100
 
@@ -107,10 +107,10 @@
107
107
  const src = `{
108
108
  "FirstName": {
109
109
  "itemType": "text",
110
- "x": "236",
110
+ "x": 236,
111
- "y": "145",
111
+ "y": 145,
112
- "fontSize": "20",
112
+ "fontSize": 20,
113
- "useKerning": "false"
113
+ "useKerning": false
114
114
  },
115
115
  "Gender": {
116
116
  "itemType": "circle",
@@ -131,8 +131,8 @@
131
131
 
132
132
  func walk(s interface{}) string {
133
133
  switch v := s.(type) {
134
- case int:
134
+ case bool:
135
- return fmt.Sprintf("int(%d)", v)
135
+ return fmt.Sprintf("bool(%v)", v)
136
136
  case float64:
137
137
  return fmt.Sprintf("float64(%f)", v)
138
138
  case string:

8

typo修正

2021/04/16 11:29

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -92,7 +92,7 @@
92
92
  ## 任意のJSONを解釈したい場合
93
93
 
94
94
  hogesの型をinterface{}にすれば任意のJSONのパースは完了します。
95
- 以下のように型スイッチを再的に組むことで各値にアクセスできます。
95
+ 以下のように型スイッチを再的に組むことで各値にアクセスできます。
96
96
 
97
97
  [https://play.golang.org/p/kbOCT3qMj3B](https://play.golang.org/p/kbOCT3qMj3B)
98
98
  ```go

7

やっと質問の意図をつかみました

2021/04/16 11:20

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -87,4 +87,76 @@
87
87
  }
88
88
  ```
89
89
 
90
- 実行例: [https://play.golang.org/p/ERBnucspJha](https://play.golang.org/p/ERBnucspJha)
90
+ 実行例: [https://play.golang.org/p/ERBnucspJha](https://play.golang.org/p/ERBnucspJha)
91
+
92
+ ## 任意のJSONを解釈したい場合
93
+
94
+ hogesの型をinterface{}にすれば任意のJSONのパースは完了します。
95
+ 以下のように型スイッチを再起的に組むことで各値にアクセスできます。
96
+
97
+ [https://play.golang.org/p/kbOCT3qMj3B](https://play.golang.org/p/kbOCT3qMj3B)
98
+ ```go
99
+ package main
100
+
101
+ import (
102
+ "encoding/json"
103
+ "fmt"
104
+ "strings"
105
+ )
106
+
107
+ const src = `{
108
+ "FirstName": {
109
+ "itemType": "text",
110
+ "x": "236",
111
+ "y": "145",
112
+ "fontSize": "20",
113
+ "useKerning": "false"
114
+ },
115
+ "Gender": {
116
+ "itemType": "circle",
117
+ "male": {
118
+ "x": "359",
119
+ "y": "162",
120
+ "width": "9",
121
+ "height": "9"
122
+ },
123
+ "female": {
124
+ "x": "373",
125
+ "y": "162",
126
+ "width": "9",
127
+ "height": "9"
128
+ }
129
+ }
130
+ }`
131
+
132
+ func walk(s interface{}) string {
133
+ switch v := s.(type) {
134
+ case int:
135
+ return fmt.Sprintf("int(%d)", v)
136
+ case float64:
137
+ return fmt.Sprintf("float64(%f)", v)
138
+ case string:
139
+ return fmt.Sprintf("string(%q)", v)
140
+ case []interface{}:
141
+ items := []string{}
142
+ for _, value := range v {
143
+ items = append(items, walk(value))
144
+ }
145
+ return fmt.Sprintf("[%s]", strings.Join(items, " "))
146
+ case map[string]interface{}:
147
+ items := []string{}
148
+ for key, value := range v {
149
+ items = append(items, fmt.Sprintf("%q:%s", key, walk(value)))
150
+ }
151
+ return fmt.Sprintf("{%s}", strings.Join(items, " "))
152
+ default:
153
+ panic("unkown type")
154
+ }
155
+ }
156
+
157
+ func main() {
158
+ var hoges interface{}
159
+ json.Unmarshal([]byte(src), &hoges)
160
+ fmt.Print(walk(hoges))
161
+ }
162
+ ```

6

実行例追加

2021/04/16 11:19

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -85,4 +85,6 @@
85
85
  Male Male `json:"male"`
86
86
  Female Female `json:"female"`
87
87
  }
88
- ```
88
+ ```
89
+
90
+ 実行例: [https://play.golang.org/p/ERBnucspJha](https://play.golang.org/p/ERBnucspJha)

5

追記の追記の追記

2021/04/16 08:08

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -48,4 +48,41 @@
48
48
  ```go
49
49
  male := hoges["Gender"]["male"].(map[string]interface{})
50
50
  ```
51
- としてmaleやfemaleの内容を取り出すことはできます。
51
+ としてmaleやfemaleの内容を取り出すことはできます。
52
+
53
+ ## 追記の追記の追記
54
+
55
+ JSONがこの例示のまま可変要素が無く、構造が安定していると仮定するなら、
56
+ このJSONを[JSON-to-Go](https://mholt.github.io/json-to-go/)に投げ込んでみましょう。
57
+
58
+ 以下のような結果が得られますので、「AutoGenerated」型の変数で受けることができると思います。
59
+ ```go
60
+ type AutoGenerated struct {
61
+ FirstName FirstName `json:"FirstName"`
62
+ Gender Gender `json:"Gender"`
63
+ }
64
+ type FirstName struct {
65
+ ItemType string `json:"itemType"`
66
+ X string `json:"x"`
67
+ Y string `json:"y"`
68
+ FontSize string `json:"fontSize"`
69
+ UseKerning string `json:"useKerning"`
70
+ }
71
+ type Male struct {
72
+ X string `json:"x"`
73
+ Y string `json:"y"`
74
+ Width string `json:"width"`
75
+ Height string `json:"height"`
76
+ }
77
+ type Female struct {
78
+ X string `json:"x"`
79
+ Y string `json:"y"`
80
+ Width string `json:"width"`
81
+ Height string `json:"height"`
82
+ }
83
+ type Gender struct {
84
+ ItemType string `json:"itemType"`
85
+ Male Male `json:"male"`
86
+ Female Female `json:"female"`
87
+ }
88
+ ```

4

typo-fix

2021/04/16 08:05

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -36,9 +36,11 @@
36
36
  以下の構造を期待しますが、孫にオブジェクト以外が現れる現状のJSONデータは適合できません。
37
37
  ルートがオブジェクト、子がオブジェクトという構造が守られていますが、孫はオブジェクトだったり数値だったり文字列だったりしているので、孫をオブジェクトとしてParseすることはできません。
38
38
 
39
+ ```
39
40
  - ルートオブジェクト
40
- - 子オブジェクト
41
+ - 子オブジェクト
41
- - 孫オブジェクト
42
+ - 孫オブジェクト
43
+ ```
42
44
 
43
45
  孫の型がばらついているので孫は「interface{}」でで受けるべきなのです。
44
46
 

3

追記の追記

2021/04/16 03:35

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -28,4 +28,22 @@
28
28
  - maleとfemaleが同時に存在するのは矛盾していて合わない気がします。
29
29
 
30
30
  今のJSON構造を「UIのフォームレイアウト定義」すると以下の点に疑問があり意図が掴めません
31
- - itemType=circleに複数のmale、femaleを許容するのが不自然。
31
+ - itemType=circleに複数のmale、femaleを許容するのが不自然。
32
+
33
+ ## 追記の追記
34
+
35
+ JSONのツリー構造を「map[string]map[string]map[string]interface{}」で受けるとき、
36
+ 以下の構造を期待しますが、孫にオブジェクト以外が現れる現状のJSONデータは適合できません。
37
+ ルートがオブジェクト、子がオブジェクトという構造が守られていますが、孫はオブジェクトだったり数値だったり文字列だったりしているので、孫をオブジェクトとしてParseすることはできません。
38
+
39
+ - ルートオブジェクト
40
+ - 子オブジェクト
41
+ - 孫オブジェクト
42
+
43
+ 孫の型がばらついているので孫は「interface{}」でで受けるべきなのです。
44
+
45
+ その上で、
46
+ ```go
47
+ male := hoges["Gender"]["male"].(map[string]interface{})
48
+ ```
49
+ としてmaleやfemaleの内容を取り出すことはできます。

2

UIのレイアウト定義という解釈

2021/04/16 03:34

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -25,4 +25,7 @@
25
25
 
26
26
  今のJSON構造は「個人の情報と解釈」すると以下の点に疑問があり意図が掴めません
27
27
  - FirstNameにValueに相当するものがないとか、
28
- - maleとfemaleが同時に存在するのは矛盾していて合わない気がします。
28
+ - maleとfemaleが同時に存在するのは矛盾していて合わない気がします。
29
+
30
+ 今のJSON構造を「UIのフォームレイアウト定義」すると以下の点に疑問があり意図が掴めません
31
+ - itemType=circleに複数のmale、femaleを許容するのが不自然。

1

追記

2021/04/16 00:16

投稿

nobonobo
nobonobo

スコア3367

answer CHANGED
@@ -4,4 +4,25 @@
4
4
  - Goにジェネリクスはまだありません(早ければ次期リリースGo1.17に載るかもしれません)
5
5
  - JSON文字列の内容をみると受け皿であるhogesの型「map[string]map[string]map[string]interface{}」はミスマッチです
6
6
 
7
- ご自身で書いている「map[string]map[string]interface{}」という型指定が正解だと思うのですが。
7
+ ご自身で書いている「map[string]map[string]interface{}」という型指定が正解だと思うのですが。
8
+
9
+ ## 追記
10
+
11
+ 「構造体を作らないとダメか」という問いは「どちらでも対応できます」が構造体を作るのがおすすめです。
12
+
13
+ 複雑な構造をGoのJSONで扱う方法はいくつか手法があります。
14
+ - json.RawMessageを使った多段階デコード/エンコード
15
+ - ommitを使った未使用フィールドの省略
16
+ これらを駆使して適切な構造体を定義してやるのがGoにとっての適切なやり方になると思います。
17
+
18
+ 質問の意図がつかめない原因は具体的に何をJSONで表現しようとしているのかがわからないためです。
19
+ 「私だったらこうします」というアドバイスができません。
20
+
21
+ アドバイスが必要ならJSON構造の具体的な意図を解説して欲しい。
22
+
23
+ - 各フィールドの値には具体的にどんな情報を載せたいのでしょうか?
24
+ - itemTypeが必要な理由はなんでしょうか?
25
+
26
+ 今のJSON構造は「個人の情報と解釈」すると以下の点に疑問があり意図が掴めません
27
+ - FirstNameにValueに相当するものがないとか、
28
+ - maleとfemaleが同時に存在するのは矛盾していて合わない気がします。