Go에서 구성의 길고 짧은 구문 읽기

8378 단어 gotutorial
다음과 같은 구성 파일이 있다고 가정해 보겠습니다. (저는 json을 사용합니다.)

짧은 구문입니다.

{
    "network": "test-network"
}


긴 구문

{
    "network": {
        "name": "test-network",
        "description": "for testing purposes"
    }
}


이 구성을 읽을 때 우리는 개체를 구문 분석하고 쓰기 위해 자체 디코더 기능을 제공해야 합니다.

그 전에 예제를 확인해 보겠습니다.

먼저 길고 짧은 형식의 구조체를 만들고 언마샬링을 시도합니다.

package main

import (
    "encoding/json"
    "fmt"
)

type NetworkDescription struct {
    Name        string `json:"name"`
    Description string `json:"description"`
}

type NetworkLong struct {
    Network NetworkDescription `json:"network"`
}

type NetworkShort struct {
    Network string `json:"network"`
}

func main() {
    networkLongTest1 := &NetworkLong{}
    err := json.Unmarshal([]byte(`{"network":{"name":"foo","description":"bar"}}`), networkLongTest1)
    fmt.Printf("%#v\nErr: %v", networkLongTest1, err)

    networkLongTest2 := &NetworkLong{}
    err = json.Unmarshal([]byte(`{"network":"foo"}`), networkLongTest2)
    fmt.Printf("%#v\nErr: %v", networkLongTest2, err)
}


결과는 분명히 두 번째 시도에서 오류를 제공합니다.

$ go run main.go
&main.NetworkLong{Network:main.NetworkDescription{Name:"foo", Description:"bar"}}
Err: <nil>
&main.NetworkLong{Network:main.NetworkDescription{Name:"", Description:""}}
Err: json: cannot unmarshal string into Go struct field NetworkLong.network of type main.NetworkDescription


이제 사용자 지정 Unmarshaler의 인터페이스 구현에서 이 오류를 사용할 수 있습니다.

언마샬러에 stdlibjson를 사용하고 있으므로 언마샬러 인터페이스에는 하나의 기능UnmarshalJSON([]byte) error이 있습니다.

새로운 구조체 유형을 생성하고 사용할 수 있지만 짧은 버전을 긴 버전으로 바꿀 것이기 때문에 NetworkLong 구조체를 수정하겠습니다.

type NetworkLong struct {
    Network NetworkDescription `json:"network"`
}

func (n *NetworkLong) UnmarshalJSON(b []byte) error {
    // change type to don't use our custom unmarshal
    type longFormat NetworkLong
    nLong := &longFormat{}
    err := json.Unmarshal(b, &nLong)
    if err != nil {
        nShort := &NetworkShort{}
        err = json.Unmarshal(b, nShort)
        if err != nil {
            return err
        }

        n.Network = NetworkDescription{
            Name: nShort.Network,
        }

        return nil
    }

    *n = NetworkLong(*nLong)

    return nil
}


그리고 우리의 결과는

&main.NetworkLong{Network:main.NetworkDescription{Name:"foo", Description:"bar"}}
Err: <nil>
&main.NetworkLong{Network:main.NetworkDescription{Name:"foo", Description:""}}
Err: <nil>


체크인playground

좋은 웹페이지 즐겨찾기