首頁 >後端開發 >Golang >我有幾個結構相同的 JSON。他們的物件是物件數組。如何將這些數組附加到一個陣列中?

我有幾個結構相同的 JSON。他們的物件是物件數組。如何將這些數組附加到一個陣列中?

WBOY
WBOY轉載
2024-02-08 20:57:11977瀏覽

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

問題內容

我想做的事:

我想向此 url 發送多個 get 請求: https://catalog.wb.ru/brands/m/catalog?page=1&limit=300&brand=5786&dest=-1257786&sort=pricedown 然後收集「產品」物件內的所有資料。鍵“page”的值會自動遞增以取得所有頁面的資料。

實際上,我不太確定是否真的需要編寫一個 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刪除