在Go中解析JSON

This is an example of JSON output when calling 'ListObjects' for AWS S3

{
    "Contents": [{
        "ETag": "9e2bc2894b23742b7bb688c646c6fee9",
        "Key": "DSC-0237.jpg",
        "LastModified": "2017-09-06 21:53:15 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }, {
        "ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
        "Key": "DSC-0238.jpg",
        "LastModified": "2017-09-06 21:52:24 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }, {
        "ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
        "Key": "DSC-0239.jpg",
        "LastModified": "2017-09-06 21:53:01 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }],
    "IsTruncated": false,
    "Marker": "",
    "MaxKeys": 5,
    "Name": "test-bucket-x011pp3",
    "Prefix": ""
}

How do I parse this in Go? Chiefly I am interested in collecting:

  • Bucket Name
  • Key
  • Size
  • Owner's DisplayName
  • LastModified

I am coming from Python and in Python it would be something really simple like:

json_result = json.loads(json_string)
bucket_name = json_result['Name']
for idx, obj in enumerate(json_result['Contents']):
    key = obj['Key']
    size = obj['Size']
    lastmod = obj['LastModified']
    owner= obj['Owner']['DisplayName']

Thank you for the help!

It is something like this

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
)

var jsonData = []byte(`
{
    "Contents": [{
        "ETag": "9e2bc2894b23742b7bb688c646c6fee9",
        "Key": "DSC-0237.jpg",
        "LastModified": "2017-09-06 21:53:15 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }, {
        "ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
        "Key": "DSC-0238.jpg",
        "LastModified": "2017-09-06 21:52:24 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }, {
        "ETag": "\"9e2bc2894b23742b7bb688c646c6fee9\"",
        "Key": "DSC-0239.jpg",
        "LastModified": "2017-09-06 21:53:01 +0000 UTC",
        "Owner": {
            "DisplayName": "demo-user",
            "ID": "a9e2f170a6880f1d61852df8e523e88ca2a2b7abd093476cc93f1239ab5063c6"
        },
        "Size": 117904,
        "StorageClass": "STANDARD"
    }],
    "IsTruncated": false,
    "Marker": "",
    "MaxKeys": 5,
    "Name": "test-bucket-x011pp3",
    "Prefix": ""
}`,
)

type Response struct {
    Contents    []*Content
    IsTruncated bool
    Marker      string
    MaxKeys     int
    Name        string
    Prefix      string
}

type Content struct {
    ETag         string
    Key          string
    LastModified string
    Owner        *Owner
    Size         int
    StroageClass string
}

type Owner struct {
    DisplayName string
    ID          string
}

func main() {
    resp := &Response{}

    if err := json.NewDecoder(bytes.NewBuffer(jsonData)).Decode(resp); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%#v", resp)
}

Try it in the Go Playground

And you should read this https://golang.org/pkg/encoding/json/

See https://golang.org/pkg/encoding/json

You annotate a struct with JSON fields that should be unmarshalled from the buffer of JSON, something like this:

type AWSObject struct {
    Size  int            `json:"Size"`
    Key   string         `json:"key"`
    Owner AWSObjectOwner `json:"Owner"`
}

type AWSObjectOwner struct {
    DisplayName          `json:"DisplayName"`
}

var awsObjects []AWSObject
err = json.Unmarshal(jsonBuffer, &awsObjects)
if err != nil {
    fmt.Printf("Error unmarshaling objects: " + err.Error() + "
")
    ...
}

Using quicktype, I generated your model, marshaling code, and usage instructions:

// To parse this JSON data, add this code to your project and do:
//
//    r, err := UnmarshalListObjectsResponse(bytes)
//    bytes, err = r.Marshal()

package main

import "encoding/json"

func UnmarshalListObjectsResponse(data []byte) (ListObjectsResponse, error) {
    var r ListObjectsResponse
    err := json.Unmarshal(data, &r)
    return r, err
}

func (r *ListObjectsResponse) Marshal() ([]byte, error) {
    return json.Marshal(r)
}

type ListObjectsResponse struct {
    Contents    []Content `json:"Contents"`
    IsTruncated bool      `json:"IsTruncated"`
    Marker      string    `json:"Marker"`
    MaxKeys     int64     `json:"MaxKeys"`
    Name        string    `json:"Name"`
    Prefix      string    `json:"Prefix"`
}

type Content struct {
    ETag         string `json:"ETag"`
    Key          string `json:"Key"`
    LastModified string `json:"LastModified"`
    Owner        Owner  `json:"Owner"`
    Size         int64  `json:"Size"`
    StorageClass string `json:"StorageClass"`
}

type Owner struct {
    DisplayName string `json:"DisplayName"`
    ID          string `json:"ID"`
}

As others suggested, it's probably best to use the AWS SDK for Go, but this method may be useful in general the next time you need to parse arbitrary JSON.