LoginSignup
3
2

More than 5 years have passed since last update.

Go と Json の扱い

Posted at

前回の続きで、下記の構造体の理解をします。前回はポインター面でしたが、今回は JSON にフォーカスして見ます。

// DataFactory is the DataFactory Response
type DataFactory struct {
    autorest.Response      `json:"-"`
    ID                     *string             `json:"id,omitempty"`       // the identifying URL of the Data Factory.
    Name                   *string             `json:"name,omitempty"`     // the name of the data factory.
    Type                   *string             `json:"type,omitempty"`     // Resource Type
    Location               *string             `json:"location,omitempty"` // the supported Azure location of data factory.
    Tags                   *map[string]*string `json:"tags,omitempty"`     // A list of key-value pairs that describe the resource.
    *DataFactoryProperties `json:"properties,omitempty"`
}

// DataFactoryProperties is the Property of DataFactory
type DataFactoryProperties struct {
    DataFactoryID     *string `json:"datafactoryId,omitempty"`     // Auto-generated ID for this Data Factory.
    ProvisioningState *string `json:"provisioningState,omitempty"` // the current provisioning state of the Data Factory.
    Error             *string `json:"error,omitempty"`             // whether an error occurred during deployment.
    ErrorMessage      *string `json:"errorMessage,omitempty"`      // Message related to the error.
}

JSON を扱う (Unmarshall)

この構造体は、REST-API の戻り値をあらわしたものです。それをシュミレートして見ましょう。

func main() {
    body := `
{  
  "name": "test",  
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/adf/providers/Microsoft.DataFactory/datafactories/test",  
  "type": "Microsoft.DataFactory/datafactories",  
  "location": "westus",  
  "tags": {},  
  "properties": {  
    "dataFactoryId": "39d4e663-cfcb-4ee9-ad19-92cf87de9197",
    "provisioningState": "Succeeded",  
    "error": null,  
    "errorMessage": null  
  }  
} 
`

    var response DataFactory
    if err := json.Unmarshal([]byte(body), &response); err != nil {
        log.Fatal(err)
    }

    fmt.Println("DataFactoryId: ", *response.DataFactoryProperties.DataFactoryID)
    fmt.Println("Type: ", *response.Type)
    fmt.Println("Error: ", response.Error)

ヒアドキュメントで強引にレスポンスボディ値を作って、それをアンマーシャルして、正しく、構造体にセットされているかの確認です。しっかりできていますね。

$ go run cmd/client/main.go 
DataFactoryId:  39d4e663-cfcb-4ee9-ad19-92cf87de9197
Type:  Microsoft.DataFactory/datafactories
Error:  <nil>

ピックアップしたものですが、しっかりと帰ってきています。結構楽ですね。
さらにコードを書いていきます。

Marshal

次は逆で、構造体から JSON へ。これも簡単ですね。前回のポインタの回でお話しした通り、フィールドがポインタなので、値のセットが面倒です。(が、本番は、受け取るだけなのでこのような面倒なのは不要)さて実行。

func toAddress(str string) *string {
    return &str
}

     :

    adf := DataFactory{
        toAddress("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/adf/providers/Microsoft.DataFactory/datafactories/test"),
        toAddress("test"),
        toAddress("Microsoft.DataFactory/datafactories"),
        toAddress("westus"),
        &map[string]*string{"environemnt": toAddress("test")},
        &DataFactoryProperties{
            toAddress("39d4e663-cfcb-4ee9-ad19-92cf87de9197"),
            toAddress("Succeeded"),
            nil,
            nil,
        },
    }

    b, _ := json.Marshal(adf)
    fmt.Println("----json result---")
    fmt.Println(string(b))

実行結果

----json result---
{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/adf/providers/Microsoft.DataFactory/datafactories/test","name":"test","type":"Microsoft.DataFactory/datafactories","location":"westus","tags":{"environemnt":"test"},"properties":{"datafactoryId":"39d4e663-cfcb-4ee9-ad19-92cf87de9197","provisioningState":"Succeeded"}}

Indent

ぐぬう。きっちゃない。もうちょっと読みやすくしたい。と思っていたら、Indent というそれっぽいメソッドがありましたので使って見ます。

    b, _ := json.Marshal(adf)
    fmt.Println("----json result---")
    fmt.Println(string(b))
    fmt.Println("----Format---")
    var result bytes.Buffer
    json.Indent(&result, b, "", "  ")
    result.WriteTo(os.Stdout)

Marshal したものを、Indent メソッドに渡しています。ここでは、result のポインタを渡しています。b が、JSON をマーシャル、つまり、構造体に入れたものです。第3引数は、プレフィックス、第4引数は、インデントです。さて、実行。

----Format---
{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/adf/providers/Microsoft.DataFactory/datafactories/test",
  "name": "test",
  "type": "Microsoft.DataFactory/datafactories",
  "location": "westus",
  "tags": {
    "environemnt": "test"
  },
  "properties": {
    "datafactoryId": "39d4e663-cfcb-4ee9-ad19-92cf87de9197",
    "provisioningState": "Succeeded"
  }
}

随分と見やすくなりました。残りは、最初の構造体についていた記号です。

Json Marshal, Unmarshal のための記号

func Marshal

Marshall に意味合いがすべての乗っていました。

type DataFactory struct {
    autorest.Response      `json:"-"`
    ID                     *string             `json:"id,omitempty"`       // the identifying URL of the Data Factory.
    Name                   *string             `json:"name,omitempty"`  

日本語で書いて見ます。(抜粋)

// JSON上の "myName" を Field フィールドにマップ
Field int `json:"myName"`

// JSON上の "myName" をField フィールドにマップ
// かつ該当するフィールドが、empty であれば、省略される
Field int `json:"myName,omitempty"`

// Field という名前のフィールドと、JSON 上のフィールドも同じ名前
// 該当フィールドが、empty であれば、省略される。
Field int `json:",omitempty"`

// Field という名前のフィールドは無視される
Field int `json:"-"`

// JSON のField に該当して、かつそのキーが "-," に該当する
Field int `json:"-,"`

よし、これで全部理解できました。

リソース

3
2
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
3
2