2016-08-15 142 views
1

這裏是Golang的新手,我試圖獲得一個結構來轉換爲我的其他應用程序將使用的JSON對象。在Golang中將結構轉換爲JSON

預期的響應將是這個樣子......

"access": { 
     "STOCK": "1", 
     "FOREX": "1", 
     "WEBFOREX": "1", 
     "WEBSTOCK": "1" 
    }, 
"subscription_group_dates": { 
     "32": { 
      "START_DATE": 1464753600, 
      "END_DATE": 1472616000 
      }, 
     "42": { 
      "START_DATE": 1470024000, 
      "END_DATE": 1472616000 
      } 
    } 

我已經留在對象的「訪問」的一部分,以顯示我知道的工作零件。爲簡潔起見,其他所有內容均被省略。對我來說,困難的部分是處理golang中結構的嵌套本質......下面的結構我認爲會起作用,但我不確定語法。

在SubscriptionGroupDates類型下...我可以使用map [string]結構並嵌入剩下的內容嗎?見下面

type UCSUserAccess struct { 
    Groups   map[string]string   `json:"groups"` 
    Access   map[string]string   `json:"access"` 
    IsExpert  string      `json:"isExpert"` 
    SubscriptionGroupDates map[string]struct { 
     GroupID struct { 
      StartDate map[string]int `START_DATE` 
      EndDate map[string]int `END_DATE` 
      } 
    } `json:"subscription_group_dates"` 
} 

另外...我已經在導入部分導入了「時間」庫。我將如何使用它來將日期聲明爲時間對象? (而不是圖[字符串] INT)

由於

回答

1

1-你可以使用MarshalUnmarshal時間,這樣工作的示例代碼:

package main 

import (
    "encoding/json" 
    "fmt" 
    "log" 
    "strconv" 
    "time" 
) 

type UCSUserAccess struct { 
    Groups     map[string]string `json:"groups"` 
    Access     map[string]string `json:"access"` 
    IsExpert    string   `json:"isExpert"` 
    SubscriptionGroupDates map[string]struct { 
     StartDate Time `json:"START_DATE"` 
     EndDate Time `json:"END_DATE"` 
    } `json:"subscription_group_dates"` 
} 

type Time time.Time 

func (t Time) MarshalJSON() ([]byte, error) { 
    data := []byte(fmt.Sprint(time.Time(t).UTC().Unix())) 
    return data, nil 
} 
func (t *Time) UnmarshalJSON(data []byte) error { 
    i, e := strconv.ParseInt(string(data), 10, 64) 
    *t = Time(time.Unix(i, 0).UTC()) 
    return e 
} 
func (t Time) String() string { 
    return time.Time(t).UTC().String() 
} 

func main() { 
    str := `{ 
"access": { 
     "STOCK": "1", 
     "FOREX": "1", 
     "WEBFOREX": "1", 
     "WEBSTOCK": "1" 
    }, 
"subscription_group_dates": { 
     "32": { 
      "START_DATE": 1464753600, 
      "END_DATE": 1472616000 
      }, 
     "42": { 
      "START_DATE": 1470024000, 
      "END_DATE": 1472616000 
      } 
    } 
    }` 
    var d UCSUserAccess 
    err := json.Unmarshal([]byte(str), &d) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(d) 

    fmt.Println() 
    body, err := json.Marshal(d) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(string(body)) 
} 

2-您可以使用MarshalUnmarshal時間,像這樣簡化的工作示例代碼:

package main 

import (
    "encoding/json" 
    "fmt" 
    "log" 
    "strconv" 
    "time" 
) 

type UCSUserAccess struct { 
    StartDate Time `json:"START_DATE"` 
} 

type Time time.Time 

func (t Time) MarshalJSON() ([]byte, error) { 
    data := []byte(fmt.Sprint(time.Time(t).UTC().Unix())) 
    return data, nil 
} 
func (t *Time) UnmarshalJSON(data []byte) error { 
    i, e := strconv.ParseInt(string(data), 10, 64) 
    *t = Time(time.Unix(i, 0).UTC()) 
    return e 
} 
func (t Time) String() string { 
    return time.Time(t).UTC().String() 
} 

func main() { 
    str := `{ 
      "START_DATE": 1464753600 
    }` 
    var d UCSUserAccess 
    err := json.Unmarshal([]byte(str), &d) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(d) 

    fmt.Println() 
    body, err := json.Marshal(d) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(string(body)) 
} 

3-你也可以使用int64時間,像這樣的工作示例代碼:

package main 

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

type GroupID struct { 
    StartDate int64 `json:"START_DATE"` 
    EndDate int64 `json:"END_DATE"` 
} 

func (t *GroupID) Start() time.Time { 
    return time.Unix(t.StartDate, 0) 
} 
func (t *GroupID) End() time.Time { 
    return time.Unix(t.EndDate, 0) 
} 

type UCSUserAccess struct { 
    Access     map[string]string `json:"access"` 
    SubscriptionGroupDates map[string]GroupID `json:"subscription_group_dates"` 
} 

func main() { 
    str := `{ 
"access": { 
     "STOCK": "1", 
     "FOREX": "1", 
     "WEBFOREX": "1", 
     "WEBSTOCK": "1" 
    }, 
"subscription_group_dates": { 
     "32": { 
      "START_DATE": 1464753600, 
      "END_DATE": 1472616000 
      }, 
     "42": { 
      "START_DATE": 1470024000, 
      "END_DATE": 1472616000 
      } 
    } 
    }` 
    var d UCSUserAccess 
    err := json.Unmarshal([]byte(str), &d) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(d) 
    gID := d.SubscriptionGroupDates["32"] 
    fmt.Println(gID.Start()) 

    fmt.Println() 
    body, err := json.Marshal(d) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(string(body)) 
} 

4-您可以使用Int64與接收器的方法,像這樣的工作示例代碼:

package main 

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

type Int64 int64 
type GroupID struct { 
    StartDate Int64 `json:"START_DATE"` 
    EndDate Int64 `json:"END_DATE"` 
} 

func (t *Int64) Time() time.Time { 
    return time.Unix(int64(*t), 0).UTC() 
} 

type UCSUserAccess struct { 
    Access     map[string]string `json:"access"` 
    SubscriptionGroupDates map[string]GroupID `json:"subscription_group_dates"` 
} 

func main() { 
    str := `{ 
"access": { 
     "STOCK": "1", 
     "FOREX": "1", 
     "WEBFOREX": "1", 
     "WEBSTOCK": "1" 
    }, 
"subscription_group_dates": { 
     "32": { 
      "START_DATE": 1464753600, 
      "END_DATE": 1472616000 
      }, 
     "42": { 
      "START_DATE": 1470024000, 
      "END_DATE": 1472616000 
      } 
    } 
    }` 
    var d UCSUserAccess 
    err := json.Unmarshal([]byte(str), &d) 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Println(d) 
    gID := d.SubscriptionGroupDates["32"] 
    fmt.Println(gID.StartDate.Time()) 

    fmt.Println() 
    body, err := json.Marshal(d) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(string(body)) 
} 
+0

@ rick-mason我希望這會有所幫助。 – 2016-08-16 02:59:11

4

您的結構有點不合適。 SubscriptionGroupDates特別是一個字符串到結構的映射,結構本身可以是一個字符串到int的映射圖,也可以是一個帶有兩個int字段的靜態結構。你有第二個結構嵌套,並且您的日期被指定爲地圖時,他們應該是整數:

type UCSUserAccess struct { 
    Groups     map[string]string `json:"groups"` 
    Access     map[string]string `json:"access"` 
    IsExpert    string    `json:"isExpert"` 
    SubscriptionGroupDates map[string]GroupID `json:"subscription_group_dates"` 
} 

type GroupID struct { 
    StartDate int `json:"START_DATE"` 
    EndDate int `json:"END_DATE"` 
} 

這給了JSON作爲您期望。例如:https://play.golang.org/p/rGm7zKJypk(通過jsonlint.com運行輸出以驗證它是如何得出的)。

至於時間戳,JSON中的時間戳存儲爲Unix時間戳。爲了讓這些成爲時間。時間,你需要自己解析它們,無論是解組後,還是通過在自定義時間類型上實現接口。有關如何做到這一點的詳細信息,請參閱this answer

1

您可以通過提供UnmarshalJSON和MarshalJSON方法來簡單地創建自己的日期。您可以通過任何方式格式化輸入的句柄並格式化輸出。

package main 

import (
    "encoding/json" 
    "fmt" 
    "strconv" 
    "strings" 
) 

type Date struct { 
    year int 
    month int 
    day int 
} 

func (t *Date) UnmarshalJSON(data []byte) (e error) { 
    trimmed := string(data) 
    trimmed = strings.TrimLeft(trimmed, "\"") 
    trimmed = strings.TrimRight(trimmed, "\"") 

    parts := strings.Split(trimmed, "-") 

    t.year, _ = strconv.Atoi(parts[0]) 
    t.month, _ = strconv.Atoi(parts[1]) 
    t.day, _ = strconv.Atoi(parts[2]) 

    return 
} 

func (t *Date) MarshalJSON() (buff []byte, e error) { 
    buff = []byte(fmt.Sprintf("\"%d-%d-%d\"", t.year, t.month, t.day)) 
    return 
} 

type Foo struct { 
    Groups map[string]string `json:"groups"` 
    Date Date    `json:"date"` 
} 

func main() { 

    f := Foo{ 
     Groups: map[string]string{ 
      "group1": "bar", 
      "group2": "baz", 
     }, 
     Date: Date{year: 2016, month: 12, day: 22}, 
    } 

    buff, _ := json.Marshal(&f) 

    fmt.Println(string(buff)) 

    json.Unmarshal(buff, &f) 

    fmt.Printf("%+v", f) 

}