Go语言 如何输入通用HTTP响应JSON

ki1q1bka  于 5个月前  发布在  Go
关注(0)|答案(3)|浏览(62)

我从某个API得到的大多数响应体都具有以下结构:

{
    "size": 2,
    "values": [
        // values whose types differ based on the endpoint that was called
    ]
}

字符串
例如,如果我点击/api/v1/cars,我会返回:

{
    "size": 1,
    "values": [
        {
            "make": "Honda",
            "year": 1994,
        }
    ]
}


如果我点击/api/v1/courses

{
    "size": 2,
    "values": [
        {
            "name": "Spanish",
            "startDate": "2023-08-07T04:00:00Z",
        },
        {
            "name": "Business",
            "startDate": "2023-08-21T04:00:00Z",
        }
    ]
}


对于泛型,它看起来像这样工作得很好:

type ResponseValue interface {
    car | course
}

type Response[T ResponseValue] struct {
    Size   int
    Values []T
}


Playground
在泛型被引入之前,如果不创建像Size这样的重复值的类型(真实的数据有比size多得多的字段),这是如何实现的呢?

type carResp struct {
    Size int
    Values []car
}

type coursesResp struct {
    Size int
    Values []course
}

sdnqo3pr

sdnqo3pr1#

你会嵌入一般的React的东西,

type Resp struct {
    Size int
}

type coursesResp struct {
    Resp
    Values []course
}

type carResp struct {
    Resp
    Values []car
}

字符串

lzfw57am

lzfw57am2#

这种 Package 的数据结构被称为“envelope”。这对于返回分页响应的API来说很常见。在go有泛型之前,envelope是用接口类型 Package 的:

type Person struct {
    Name string `json:"name"`
}

type PaginationEnvelope struct {
    Items      interface{} `json:"items"`
    ThisPage   int         `json:"thisPage"`
    PageSize   int         `json:"pageSize"`
}

...

envelope := &PaginationEnvelope{}
persons := db.persons.retrieveAll()
envelope.Items = persons

return JSON(envelope)

字符串
结果:

{
    "items": [
        { "name": "Alice" },
        { "name": "Bob" }
    ],
    "thisPage": 1,
    "pageSize": 2
}

fruv7luv

fruv7luv3#

Values字段decompose为类型any

type response struct {
    Size   int
    Values any
}

字符串
要解封response,请将Values设置为所需类型的指针。json.Unmarshal函数解码为该值。

func unmarshal(data []byte, pvalues any) (*response, error) {
    r := response{Values: pvalues}
    err := json.Unmarshal(data, &r)
    return &r, err
}


像这样使用它:

respCars := []byte(`{"size": 1, "values": [{"make": "Honda", "year": 1999}]}`)
var cars []car
r, err := unmarshal(respCars, &cars)
fmt.Println(err, r.Size, cars)

respCourses := []byte(`{"size": 1, "values": [{"name": "Math", "startDate": "2023-08-21T04:00:00Z"}]}`)
var courses []course
r, err = unmarshal(respCourses, &courses)
fmt.Println(err, r.Size, courses)


https://go.dev/play/p/qVxYN4h4tlA

相关问题