首页 >后端开发 >Golang >我有几个结构相同的 JSON。他们的对象是对象数组。如何将这些数组附加到一个数组中?

我有几个结构相同的 JSON。他们的对象是对象数组。如何将这些数组附加到一个数组中?

WBOY
WBOY转载
2024-02-08 20:57:11986浏览

我有几个结构相同的 JSON。他们的对象是对象数组。如何将这些数组附加到一个数组中?

问题内容

我想做的事:

我想向此 url 发送多个 get 请求: https://catalog.wb.ru/brands/m/catalog?page=1&limit=300&brand=5786&dest=-1257786&sort=pricedown 然后收集“产品”对象内的所有数据。键“p​​age”的值会自动递增以获取所有页面的数据。

实际上,我不太确定是否真的需要编写一个 json 来将其发送到前端。也许当我在 for 循环中收到新响应时发送不同的请求会更好?

我做了什么:

制作了正确的结构。通过单个请求,一切正常。

创建了 requestbodybytes []byteproductsbytes []byte,以便将它们与 ioutil.readall 中的 []bytes 一起附加。 打印 requestbodybytes 的长度我发现它随着每个请求而扩展,但是在我解组它之后,我在输出中看到空结构。

我知道发生这种情况是因为每个请求我都会收到 type response 的新 json。但是,如果我需要由 type response 的多个 json 中的“产品”对象组成的 product structs 切片,该怎么办?

注意:需要在 for 循环内初始化 requestbodybytes 以使用它来停止发送请求,因为当页面上没有信息时,服务器会给出 200 代码和空 json。

提前谢谢您!

const URL = "https://catalog.wb.ru/brands/m/catalog?page=%d&limit=300&brand=5786&dest=-1257786&sort=pricedown"

type Response struct {
    Data struct {
        Products []Product `json:"products"`
    } `json:"data"`
}

type Product struct {
    ID     int     `json:"id"`
    Name   string  `json:"name"`
    Price  int     `json:"priceU"`
    Rating float32 `json:"reviewRating"`
    Sale   int     `json:"sale"`
    New    bool    `json:"isNew"`
}

func main() {
    var response Response
    var products Response //Also tried to make it []Response
    var ProductsBytes []byte

    for i := 1; ; i++ {
        resp, err := http.Get(fmt.Sprintf(URL, i))
        if err != nil {
            fmt.Printf("#1 Error: %s", err)
        }
        defer resp.Body.Close()

        bytes, err := ioutil.ReadAll(resp.Body)
        var requestBodyBytes []byte
        requestBodyBytes = append(requestBodyBytes, bytes...)
        ProductsBytes = append(ProductsBytes, bytes...)

        json.Unmarshal(requestBodyBytes, &response)

        fmt.Println(resp.Status)
        fmt.Printf("\nSlice from page #%d\nLength of bytes: %d\n", i, len(bytes))
        fmt.Printf("Length of finalResult: %d\n", len(requestBodyBytes))
        if len(response.Data.Products) == 0 {
            fmt.Println("There's no more data")
            break
        }
    }

    json.Unmarshal(ProductsBytes, &products)

    fmt.Println(response)
    fmt.Println(products)
    fmt.Println(len(products))
}

正确答案


没有理由收集所有原始响应字节。只需单独解组每个响应并将每个页面的产品附加到包含所有产品的某个切片即可。另外,在循环中调用 defer resp.body.close() 可能不是您想要的。延迟语句仅在循环结束后执行,因此连接不能重新用于请求。将循环体提取到它自己的函数中使这变得更加清晰:

package main

import (
    "encoding/json"
    "errors"
    "fmt"
    "log"
    "net/http"
)

const URL = "https://catalog.wb.ru/brands/m/catalog?page=%d&limit=300&brand=5786&dest=-1257786&sort=pricedown"

type Response struct {
    Data struct {
        Products []Product `json:"products"`
    } `json:"data"`
}

type Product struct {
    ID     int     `json:"id"`
    Name   string  `json:"name"`
    Price  int     `json:"priceU"`
    Rating float32 `json:"reviewRating"`
    Sale   int     `json:"sale"`
    New    bool    `json:"isNew"`
}

func main() {
    var allProducts []Product

    for i := 1; ; i++ {
        page, err := fetchPage(i)
        if err != nil {
            log.Fatal(err) // TODO
        }

        allProducts = append(allProducts, page...)

        if len(page) == 0 {
            break
        }
    }

    fmt.Println(allProducts)
    fmt.Println(len(allProducts))
}

func fetchPage(i int) ([]Product, error) {
    resp, err := http.Get(fmt.Sprintf(URL, i))
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return nil, errors.New(resp.Status)
    }

    var response Response
    err = json.NewDecoder(resp.Body).Decode(&response)
    if err != nil {
        return nil, err
    }

    return response.Data.Products, nil
}

以上是我有几个结构相同的 JSON。他们的对象是对象数组。如何将这些数组附加到一个数组中?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除