json - 将 `struct` 作为类型名称传递给函数参数

标签 json reflection interface go

我正在编写某种基于 RESTfull API 的对象关系映射器。 当我完成它时,我计划让它获得麻省理工学院的许可。 这个想法是使用一些第 3 方 REST API 作为数据存储,golang 客户端将查询它以获取所需的数据。

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 响应的结构名称。当前代码适用于 AEventsstruct,但我希望它可以轻松更改为 AClient 等等。

更新: 我已经查看了 https://github.com/jinzhu/gorm 的代码并找出大量我该如何实现的东西。 然后,正如我所 promise 的,我将此代码作为开源发布 - https://github.com/vodolaz095/hrorm

最佳答案

您可以使用反射,但请注意它非常重要且相对较慢。我不知道任何其他方式。

执行此操作的最简单方法是使您的参数成为 interface{} 类型,并传入您希望解码到的结构的空(未初始化)实例。我强烈建议阅读我列出的两个链接中的第二个 - 它清楚地介绍了反射以及如何使用它来解决此类问题。

关于json - 将 `struct` 作为类型名称传递给函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28329938/

相关文章:

python - json 和 simplejson Python 模块有什么区别?

java - 如何在值类型和键值对数量未知的情况下 HashMap JSON 的键值对

c# - 使用反射在某些操作系统上使用命名空间

c# - 我可以在接口(interface)上重载 == 运算符吗?

php - 缓存 API/接口(interface)以用作模型

javascript - IE8 中的 JSON 语法错误?

android - Retrofit,如何解析带有可变键的JSON对象

java - 是否可以在运行时创建 Java 模型对象并动态映射 Spring Batch Reader 中的字段?

ruby - 如何使用反射获取参数名称

interface - fortran选择按过程调用派生类型