2015-02-04 164 views
1

我正在寫一些基於RESTfull API的對象關係映射器。 我打算讓它完成MIT授權。 這個想法是使用一些第三方REST API作爲數據存儲,並且golang客戶端將查詢它以獲取所需的數據。將`struct`作爲類型名稱傳遞給函數參數

API響應是具有已知結構的JSON。

這是我的代碼:

type AClient struct { 
    Id  string `json:"id"` 
    Uid  string `json:"uid"` 
    FirstName string `json:"firstName"` 
    LastName string `json:"lastName"` 
    CreatedAt string `json:"createdAt"` 
    UpdatedAt string `json:"updatedAt"` 
    City  string `json:"city"` 
    Address string `json:"address"` 
    Telefone string `json:"telefone"` 
    Zip  string `json:"zip"` 
    Telefon string `json:"telefon"` 
    Comment string `json:"comment"` 
} 

type AEvents struct { 
    Id   string `json:"id"` 
    Security bool  `json:"security"` 
    Description string `json:"description"` 
    Good  AGood  `json:"good"` 
    Client  AClient `json:"client"` 
    Author  AAuthor `json:"author"` 
    InFuture bool  `json:"inFuture"` 
    CreatedAt time.Time `json:"createdAt"` 
    UpdatedAt time.Time `json:"updatedAt"` 
} 

type Entry struct { 
    AEvents //this have to be changed to `AClients` in runtime when needed 
} 

type ORM struct { 
    ApiUrl   string 
    ModelName  string 
    ModelInterface Entry 
    HuntKey  string 
    HuntSid  string 
    Csrf   string 
} 

func (o *ORM) Query(parameters map[string]string) ([]Entry, AMetadata, error) { 
    responseParsed := struct { 
     Status string `json:"status"` 
     Metadata AMetadata `json:"metadata"` 
     Data  []Entry `json:"data"` //todo - use o.ModelInterface 
    }{} 
    client := &http.Client{} 

    var queryString string 

    for k, v := range parameters { 
     queryString = queryString + fmt.Sprintf("%v=%v&", url.QueryEscape(k), url.QueryEscape(v)) 
    } 

    req, err := http.NewRequest("GET", fmt.Sprintf("%v%v?%v", o.ApiUrl, o.ModelName, queryString), nil) 
    fmt.Println("---------------------------------------------") 
    fmt.Println(fmt.Sprintf("[GET] %v%v?%v", o.ApiUrl, o.ModelName, queryString)) 
    req.Header.Set("huntKey", o.HuntKey) 
    if err != nil { 
     return nil, AMetadata{}, err 
    } 
    res, err1 := client.Do(req) 
    defer res.Body.Close() 
    if err1 != nil { 
     return nil, AMetadata{}, err1 
    } 
    if res.StatusCode == 200 { 
     for _, v := range res.Cookies() { 
      if v.Name == "XSRF-TOKEN" { 
       o.Csrf = v.Value 
      } 
      if v.Name == "hunt.sid" { 
       o.HuntSid = v.Value 
      } 
     } 
     fmt.Printf("CSRF %v\n", o.Csrf) 
     fmt.Printf("HuntSid %v\n", o.HuntSid) 
     fmt.Println("---------------------------------------------") 
     raw, err2 := ioutil.ReadAll(res.Body) 
     if err2 != nil { 
      return nil, AMetadata{}, err2 
     } else { 
      err2 = json.Unmarshal(raw, &responseParsed) 
      return responseParsed.Data, responseParsed.Metadata, nil 
     } 
    } else { 
     return nil, AMetadata{}, errors.New("Unable to fetch data!") 
    } 
} 

我怎樣才能讓這樣的: 當實例化對象ORM,我怎麼能傳遞結構名稱,將被用來解析JSON響應。目前的代碼與structAEvents一起使用,但是我希望它很容易改變,例如AClient等等。

UPD: 我已閱讀https://github.com/jinzhu/gorm的代碼並找出大量的東西,我該如何實現它。 根據我的承諾,我發佈此代碼作爲開源代碼 - https://github.com/vodolaz095/hrorm

回答

1

您可以使用反射,但需要警告它不平凡且相對較慢。我不知道任何其他方式。

要做到這一點最簡單的方法就是讓你的interface{}類型的參數,並傳入要解組的結構的空(初始化)實例。我強烈建議閱讀我列出的兩個鏈接中的第二個 - 它提供了反思的明確介紹以及如何使用它來解決像這樣的問題。

+0

謝謝你的回答,你能提供一些更多的見解我怎麼能做到這一點?我很新的去,我以前的語言是JavaScript – vodolaz095

相關問題