質問の意図がつかみかねていて、言えることは以下の3つです。
- TypeScriptでいう「any」に相当する型はGoでは「interface{}」です
- Goにジェネリクスはまだありません(早ければ次期リリースGo1.17に載るかもしれません)
- JSON文字列の内容をみると受け皿であるhogesの型「map[string]map[string]map[string]interface{}」はミスマッチです
ご自身で書いている「map[string]map[string]interface{}」という型指定が正解だと思うのですが。
追記
「構造体を作らないとダメか」という問いは「どちらでも対応できます」が構造体を作るのがおすすめです。
複雑な構造をGoのJSONで扱う方法はいくつか手法があります。
- json.RawMessageを使った多段階デコード/エンコード
- ommitを使った未使用フィールドの省略
これらを駆使して適切な構造体を定義してやるのがGoにとっての適切なやり方になると思います。
質問の意図がつかめない原因は具体的に何をJSONで表現しようとしているのかがわからないためです。
「私だったらこうします」というアドバイスができません。
アドバイスが必要ならJSON構造の具体的な意図を解説して欲しい。
- 各フィールドの値には具体的にどんな情報を載せたいのでしょうか?
- itemTypeが必要な理由はなんでしょうか?
今のJSON構造は「個人の情報と解釈」すると以下の点に疑問があり意図が掴めません
- FirstNameにValueに相当するものがないとか、
- maleとfemaleが同時に存在するのは矛盾していて合わない気がします。
今のJSON構造を「UIのフォームレイアウト定義」すると以下の点に疑問があり意図が掴めません
- itemType=circleに複数のmale、femaleを許容するのが不自然。
追記の追記
JSONのツリー構造を「map[string]map[string]map[string]interface{}」で受けるとき、
以下の構造を期待しますが、孫にオブジェクト以外が現れる現状のJSONデータは適合できません。
ルートがオブジェクト、子がオブジェクトという構造が守られていますが、孫はオブジェクトだったり数値だったり文字列だったりしているので、孫をオブジェクトとしてParseすることはできません。
- ルートオブジェクト
- 子オブジェクト
- 孫オブジェクト
孫の型がばらついているので孫は「interface{}」でで受けるべきなのです。
その上で、
go
1male := hoges["Gender"]["male"].(map[string]interface{})
としてmaleやfemaleの内容を取り出すことはできます。
追記の追記の追記
JSONがこの例示のまま可変要素が無く、構造が安定していると仮定するなら、
このJSONをJSON-to-Goに投げ込んでみましょう。
以下のような結果が得られますので、「AutoGenerated」型の変数で受けることができると思います。
go
1type AutoGenerated struct {
2 FirstName FirstName `json:"FirstName"`
3 Gender Gender `json:"Gender"`
4}
5type FirstName struct {
6 ItemType string `json:"itemType"`
7 X string `json:"x"`
8 Y string `json:"y"`
9 FontSize string `json:"fontSize"`
10 UseKerning string `json:"useKerning"`
11}
12type Male struct {
13 X string `json:"x"`
14 Y string `json:"y"`
15 Width string `json:"width"`
16 Height string `json:"height"`
17}
18type Female struct {
19 X string `json:"x"`
20 Y string `json:"y"`
21 Width string `json:"width"`
22 Height string `json:"height"`
23}
24type Gender struct {
25 ItemType string `json:"itemType"`
26 Male Male `json:"male"`
27 Female Female `json:"female"`
28}
実行例: https://play.golang.org/p/ERBnucspJha
任意のJSONを解釈したい場合
hogesの型をinterface{}にすれば任意のJSONのパースは完了します。
以下のように型スイッチを再帰的に組むことで各値にアクセスできます。
https://play.golang.org/p/MFEcaerWzlP
go
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "strings"
7)
8
9const src = `{
10 "FirstName": {
11 "itemType": "text",
12 "x": 236,
13 "y": 145,
14 "fontSize": 20,
15 "useKerning": false
16 },
17 "Gender": {
18 "itemType": "circle",
19 "male": {
20 "x": "359",
21 "y": "162",
22 "width": "9",
23 "height": "9"
24 },
25 "female": {
26 "x": "373",
27 "y": "162",
28 "width": "9",
29 "height": "9"
30 }
31 }
32}`
33
34func walk(s interface{}) string {
35 switch v := s.(type) {
36 case bool:
37 return fmt.Sprintf("bool(%v)", v)
38 case float64:
39 return fmt.Sprintf("float64(%f)", v)
40 case string:
41 return fmt.Sprintf("string(%q)", v)
42 case []interface{}:
43 items := []string{}
44 for _, value := range v {
45 items = append(items, walk(value))
46 }
47 return fmt.Sprintf("[%s]", strings.Join(items, " "))
48 case map[string]interface{}:
49 items := []string{}
50 for key, value := range v {
51 items = append(items, fmt.Sprintf("%q:%s", key, walk(value)))
52 }
53 return fmt.Sprintf("{%s}", strings.Join(items, " "))
54 default:
55 panic("unkown type")
56 }
57}
58
59func main() {
60 var hoges interface{}
61 json.Unmarshal([]byte(src), &hoges)
62 fmt.Print(walk(hoges))
63}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/04/15 21:47
2021/04/16 02:39
2021/04/16 03:37 編集
2021/04/16 03:58
2021/04/16 03:59
2021/04/16 04:38
2021/04/16 05:24
2021/04/16 07:21
2021/04/16 07:26
2021/04/16 08:57
2021/04/16 11:00
2021/04/17 02:49
2021/04/18 00:29
2021/04/19 01:07
2021/04/19 01:34