sách gpt4 ăn đã đi

json - 在不使用反射或复制代码的情况下从多个 JSON 数组解码实体

In lại 作者:IT王子 更新时间:2023-10-29 01:44:06 25 4
mua khóa gpt4 giày nike

我正在制作一个需要获取分页结果的 JSON API 包装器客户端,其中下一页的 URL 由上一页提供。为了减少共享相同响应格式的 100 多个实体的代码重复,我希望有一个客户端方法可以从所有分页页面中获取和解码不同的实体。

我目前在简化(伪)版本中的方法(没有错误等):

type ListResponse struct {
Data struct {
Results []interface{} `json:"results"`
Next string `json:"__next"`
} `json:"d"`
}

func (c *Client) ListRequest(uri string) listResponse ListResponse {
// Do a http request to uri and get the body
body := []byte(`{ "d": { "__next": "URL", "results": []}}`)
json.NewDecoder(body).Decode(&listResponse)
}

func (c *Client) ListRequestAll(uri string, v interface{}) {
a := []interface{}
f := c.ListRequest(uri)
a = append(a, f.Data.Results...)

var next = f.Data.Next
for next != "" {
r := c.ListRequest(next)
a = append(a, r.Data.Results...)
next = r.Data.Next
}

b, _ := json.Marshal(a)
json.Unmarshal(b, v)
}

// Then in a method requesting all results for a single entity
var entities []Entity1
client.ListRequestAll("https://foo.bar/entities1.json", &entities)

// and somewehere else
var entities []Entity2
client.ListRequestAll("https://foo.bar/entities2.json", &entities)

然而,问题是这种方法效率低下并且使用过多内存等,即首先在一般 ListResponse 中解码,结果为 []interface{}(到查看下一个 URL 并将结果连接到单个 slice 中),然后编码 []interface{} 以便在 []Entity1 的目标 slice 中直接向后解码它。

我也许可以使用 phản ánh 包来动态生成这些实体的新 slice ,直接解码到它们中,然后连接/附加它们,但是如果我理解正确,我最好不要使用 反射(reflect)除非绝对必要...

câu trả lời hay nhất

查看 encoding/json 包中的 RawMessage 类型。它允许您将 json 值的解码推迟到以后。例如:

Results []json.RawMessage `json:"results"`

甚至...

Results json.RawMessage `json:"results"`

由于 json.RawMessage 只是一个 byte slice 段,因此这将比您解码到的中间 []interface{} 更有效。

至于第二部分,关于如何在给定多个页面读取的情况下将这些组合成单个 slice ,您可以通过让调用者使用 slice 类型的 slice 来向调用者提出这个问题。

// Then in a method requesting all results for a single entity
var entityPages [][]Entity1
client.ListRequestAll("https://foo.bar/entities1.json", &entityPages)

但是,这仍然存在您的一般设计所存在的无限内存消耗问题,因为您必须一次加载所有页面/项目。您可能需要考虑更改为打开/读取抽象,例如处理文件。你会有一些返回另一种类型的 Mở 方法,像 os.File 一样,它提供了一种一次读取数据子集的方法,同时在内部请求页面和根据需要缓冲。

也许是这样的(未经测试):

type PagedReader struct {
c *Client

buffer []json.RawMessage

next string
}

func (r *PagedReader) getPage() {
f := r.c.ListRequest(r.next)
r.next = f.Data.Next
r.buffer = append(r.buffer, f.Data.Results...)
}

func (r *PagedReader) ReadItems(output []interface{}) int {
for len(output) > len(buffer) && r.next != "" {
r.getPage()
}

n := 0
for i:=0;i
json.Unmarshal(r.buffer[i], output[i] )
n++
}
r.buffer = r.buffer[n:]
return n
}

关于json - 在不使用反射或复制代码的情况下从多个 JSON 数组解码实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52027531/

25 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress