0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

goで未定義のJSONから一部の値のみ取り出す

Posted at

goに限った話ではないが、複雑なJSONから一部だけ取り出したいといった場合に、その複雑なJSONのフォーマットを構造体として定義しておくのは面倒だ。そこで型を決めずmap[string]interface{}に流し込んでおいて、あとでType-castingすれば取り出せるのだが、値が多段になっている場合など、なかなか書き方を調べるのが大変だったので、とりあえず動いたものを公開する。

対象となるJSONファイルは、このように直下にkey:valueがあるものや、valueが多段になっているもの、配列になっているものなどを想定している。

sample.json
{
    "name": "Hello",
    "value1": {
        "name":"Hello1"
    },
    "value2":[
        {"name":"Hello2-1"},
        {"name":"Hello2-2"}
    ]
}

それに対して、コマンドラインでキーワードを指定して、

jsontest ファイル名 キーワード1 キーワード2

といった使い方をする。

jsontest.go
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
)

func main() {

	flag.Parse()
	args := flag.Args()

	var fname string
	if len(args) > 0 {
		fname = args[0]
	} else {
		log.Fatal("usage: jsontest fname [key1] [key2]")
	}

	fileContent, err := ioutil.ReadFile(fname)
	if err != nil {
		log.Fatal("ReadFile Error")
	}
	fileString := string(fileContent)

	var jsonContent map[string]interface{}
	if err := json.Unmarshal([]byte(fileString), &jsonContent); err != nil {
		log.Fatal("Unmarshal Error")
	}

	if len(args) > 1 {
		var value1 interface{} = jsonContent[args[1]]
		switch t := value1.(type) {
		case string:
			fmt.Println(t)
		case interface{}: // valueの下にkey:valueがある場合(sample.jsonのvalue1)
			if len(args) > 2 {
				value2, ok := value1.(map[string]interface{})
				if ok {
					fmt.Println(value2[args[2]])
				}
			} else {
				fmt.Println(value1)
			}
		case []interface{}: // valueの下に配列がある場合(sample.jsonのvalue2)
			for _, value1 := range value1.([]interface{}) {
				if len(args) > 2 {
					value2, ok := value1.(map[string]interface{})
					if ok {
						fmt.Println(value2[args[2]])
					}
				} else {
					fmt.Println(value1)
				}
			}
		default:
			fmt.Println("default")
			fmt.Printf("%T ", t)
			fmt.Println(t)
		}
	} else { // 検索キーワードがない場合、そのまま表示する
		fmt.Println(fileContent)
	}

}

言うまでもないが、取り出すキーが決まってる場合はswitchで型ごとに分岐するのではなく一気に指定すればいい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?