공부/Go

golang convert json to interface

토고미 2021. 10. 20. 15:41

go에서 json을 파싱할때 struct 구조를 모르거나,

키값 하나만 필요한데 struct는 너무 커서 곤란할 때가 있다.

 

그럴 땐 interface를 통해 파싱하면 간편하다.

 

exampleJson이라는 변수에 json string이 담겨있다고 가정했을 때,

아래 코드로 파싱 가능하다.

const exampleJson = `{"kind":"Event","apiVersion":"events.k8s.io/v1"}`

var result map[string]interface{}

if err := json.Unmarshal([]byte(exampleJson), &result); err != nil {
	panic(err)
}

fmt.Println(result["kind"]) // Event 출력
fmt.Println(result["apiVersion"]) // events.k8s.io/v1 출력

 

만약 value값에 또 key, value형식으로 되어있다면 아래와 같이 해주면 된다.

const exampleJson = `{"kind":"Event",` +
		`"apiVersion":"events.k8s.io/v1",` +
        `"metadata":{"name":"swlee-event-test-53009236","namespace":"default"}}`

var result map[string]interface{}

if err := json.Unmarshal([]byte(exampleJson), &result); err != nil {
	panic(err)
}

fmt.Println(result["metadata"].(map[string]interface{})["name"]) // swlee-event-test-53009236 출력
fmt.Println(result["metadata"].(map[string]interface{})["namespace"]) // default 출력

 

만약 그 아래에 또 있다면, 위 처럼 반복하면된다.

next_result := result["상위 키 값"].(map[string]interface{}) 의 형태로 새로운 변수를 만든 뒤

next_result["하위 키 값"] 의 형태로 호출하면 된다.

 

참고로 string 타입으로 변환하고 싶으면 맨 마지막에 .(string)으로 하면 된다.

e.g.)

next_result := result["상위 키 값"].(map[string]interface{})["하위 키 값"].(string)

 

 

이를 좀 더 간편하게 써보기 위해 함수화 시켜보았다.

 

package main

import (
	"encoding/json"
	"fmt"
)

const exampleJson = `{"kind":"Event","apiVersion":"events.k8s.io/v1","metadata":{"name":"namespaceclaim-53009236","namespace":"default","creationTimestamp":null,"labels":{"hypercloud":"claim"}},` +
	`"eventTime":"2021-10-20T04:38:47.827281Z","reportingController":"swlee-controller","reportingInstance":"swlee-instance","action":"testAction","reason":"dangan","regarding":{"namespace":"default"},"type":"Normal","deprecatedSource":{},"deprecatedFirstTimestamp":null,"deprecatedLastTimestamp":null}`

func main() {

	var result map[string]interface{}

	if err := json.Unmarshal([]byte(exampleJson), &result); err != nil {
		panic(err)
	}

	fmt.Println(valueFromKey(result, "metadata", "name"))
	fmt.Println(valueFromKey(result, "reportingController"))
	fmt.Println(valueFromKey(result, "reportingInstance"))
	fmt.Println(valueFromKey(result, "action"))
	fmt.Println(valueFromKey(result, "reason"))
}

func valueFromKey(r map[string]interface{}, key ...string) string {
	if len(key) == 1 {
		return r[key[0]].(string)
	} else if len(key) == 2 {
		return r[key[0]].(map[string]interface{})[key[1]].(string)
	} else {
		fmt.Errorf("Not Support for 3 or more parameters.")
	}
	return ""
}

내가 임의로 만든 event 객체를 파싱해본 코드이다

하드코딩으로 2단계 키 값까지만 다뤘다.

 

결과는 아래와 같이 나온다

root@swlee:~/parsing-test# go run main.go
namespaceclaim-53009236
swlee-controller
swlee-instance
testAction
dangan