arrays - json:无法将数组解码为结构类型的 Go 值

标签 arrays json go struct

这个问题在这里已经有了答案:





panic: json: cannot unmarshal array into Go value of type main.Structure

(3 个回答)


2年前关闭。




我正在构建一个从伦敦地铁 API 读取信息的应用程序。我正在努力将 GET 请求解析为可读的内容,并且用户可以在其中访问特定的行信息。

这是我当前的代码,我正在使用一个结构来存储解码后来自 GET 请求的响应。

// struct for decoding into a structure
    var tubeStatuses struct {
        object []struct {
            typeDef      []string `json:"$type"`
            idName       string   `json:"id"`
            name         string   `json:"name"`
            modeName     string   `json:"modeName"`
            disruptions  string   `json:"disruption"`
            created      string   `json:"created"`
            modified     string   `json:"modified"`
            statusObject []struct {
                zeroObject []struct {
                    typeDef        string `json:"$type"`
                    id             int    `json:"id"`
                    statusSeverity int    `json:"statusSeverity"`
                    statusDesc     string `json:"statusSeverityDescription"`
                    created        string `json:"created"`
                    validity       string `json:"validityPeriods"`
                }
            }
            route         string `json:"routeSections"`
            serviceObject []struct {
                zeroObject []struct {
                    typeDef string `json:"$type"`
                    name    string `json:"name"`
                    uri     string `json:"uri"`
                }
            }
            crowdingObject []struct {
                typeDef string `json:"$type"`
            }
        }
    }

    fmt.Println("Now retrieving Underground line status, please wait...")
    // two variables (response and error) which stores the response from e GET request
    getRequest, err := http.Get("https://api.tfl.gov.uk/line/mode/tube/status")
    fmt.Println("The status code is", getRequest.StatusCode, http.StatusText(getRequest.StatusCode))

    if err != nil {
        fmt.Println("Error!")
        fmt.Println(err)
    }

    //close - this will be done at the end of the function
    // it's important to close the connection - we don't want the connection to leak
    defer getRequest.Body.Close()

    // read the body of the GET request
    rawData, err := ioutil.ReadAll(getRequest.Body)

    if err != nil {
        fmt.Println("Error!")
        fmt.Println(err)
    }

    jsonErr := json.Unmarshal(rawData, &tubeStatuses)

    if jsonErr != nil {
        fmt.Println(jsonErr)
    }

    //test
    fmt.Println(tubeStatuses.object[0].name)

    fmt.Println("Welcome to the TfL Underground checker!\nPlease enter a number for the line you want to check!\n0 - Bakerloo\n1 - central\n2 - circle\n3 - district\n4 - hammersmith & City\n5 - jubilee\n6 - metropolitan\n7 - northern\n8 - piccadilly\n9 - victoria\n10 - waterloo & city")

我看到的错误如下:
json: cannot unmarshal array into Go value of type struct { object []struct { typeDef []string "json:\"$type\""; idName string "json:\"id\""; name string "json:\"name\""; modeName string "json:\"modeName\""; disruptions string "json:\"disruption\""; created string "json:\"created\""; modified string "json:\"modified\""; statusObject []struct { zeroObject []struct { typeDef string "json:\"$type\""; id int "json:\"id\""; statusSeverity int "json:\"statusSeverity\""; statusDesc string "json:\"statusSeverityDescription\""; created string "json:\"created\""; validity string "json:\"validityPeriods\"" } }; route string "json:\"routeSections\""; serviceObject []struct { zeroObject []struct { typeDef string "json:\"$type\""; name string "json:\"name\""; uri string "json:\"uri\"" } }; crowdingObject []struct { typeDef string "json:\"$type\"" } } }

如何将数组解码为可读的内容?

最佳答案

以下是您的代码的工作版本。但是,您需要解决多个问题。

  • 正如本线程其他地方所提到的,您应该将 TubeStatuses(注意大写)设置为一个类型和一个数组。字段名称也应大写,以便导出。
  • 您没有考虑所有输出,并且在某些情况下类型错误。例如,您缺少一个名为“Disruption”的对象。我已经在我的示例中添加了它。 “拥挤”声明的类型错误。此外,“route”又名“routeSections”不是字符串。这是另一个数组,可能是对象,但 API 没有输出让我确定 routeSections 实际包含的内容。因此,作为一种解决方法,我将其声明为“json.RawMessage”的一种类型,以允许将其解码为 byte slice 。有关详细信息,请参阅此:https://golang.org/pkg/encoding/json/#RawMessage
  • 您不能使用 json: "$type"` .具体来说,不允许使用美元符号。
  • package main
    
    import (
        "encoding/json"
        "fmt"
        "io/ioutil"
        "net/http"
    )
    
    type TubeStatuses struct {
        TypeDef      []string `json:"type"`
        IDName       string   `json:"id"`
        Name         string   `json:"name"`
        ModeName     string   `json:"modeName"`
        Disruptions  string   `json:"disruption"`
        Created      string   `json:"created"`
        Modified     string   `json:"modified"`
        LineStatuses []struct {
            Status []struct {
                TypeDef                   string `json:"type"`
                ID                        int    `json:"id"`
                StatusSeverity            int    `json:"statusSeverity"`
                StatusSeverityDescription string `json:"statusSeverityDescription"`
                Created                   string `json:"created"`
                ValidityPeriods           []struct {
                    Period struct {
                        TypeDef  string `json: "type"`
                        FromDate string `json: "fromDate"`
                        ToDate   string `json: "toDate"`
                        IsNow    bool   `json: "isNow"`
                    }
                }
                Disruption struct {
                    TypeDef             string   `json: "type"`
                    Category            string   `json: "category"`
                    CategoryDescription string   `json: "categoryDescription"`
                    Description         string   `json: "description"`
                    AdditionalInfo      string   `json: "additionalInfo"`
                    Created             string   `json: "created"`
                    AffectedRoutes      []string `json: "affectedRoutes"`
                    AffectedStops       []string `json: "affectedStops"`
                    ClosureText         string   `json: closureText"`
                }
            }
        }
        RouteSections json.RawMessage `json: "routeSections"`
        ServiceTypes  []struct {
            Service []struct {
                TypeDef string `json:"type"`
                Name    string `json:"name"`
                URI     string `json:"uri"`
            }
        }
        Crowding struct {
            TypeDef string `json:"type"`
        }
    }
    
    func main() {
        fmt.Println("Now retrieving Underground line status, please wait...")
    
        // two variables (response and error) which stores the response from e GET request
        getRequest, err := http.Get("https://api.tfl.gov.uk/line/mode/tube/status")
        if err != nil {
            fmt.Println("Error!")
            fmt.Println(err)
        }
    
        fmt.Println("The status code is", getRequest.StatusCode, http.StatusText(getRequest.StatusCode))
    
        //close - this will be done at the end of the function
        // it's important to close the connection - we don't want the connection to leak
        defer getRequest.Body.Close()
    
        // read the body of the GET request
        rawData, err := ioutil.ReadAll(getRequest.Body)
    
        if err != nil {
            fmt.Println("Error!")
            fmt.Println(err)
        }
        ts := []TubeStatuses{}
    
        jsonErr := json.Unmarshal(rawData, &ts)
    
        if jsonErr != nil {
            fmt.Println(jsonErr)
        }
    
        //test
        fmt.Println(ts[0].Name)
    
        fmt.Println("Welcome to the TfL Underground checker!\nPlease enter a number for the line you want to check!\n0 - Bakerloo\n1 - central\n2 - circle\n3 - district\n4 - hammersmith & City\n5 - jubilee\n6 - metropolitan\n7 - northern\n8 - piccadilly\n9 - victoria\n10 - waterloo & city")
    }
    

    输出...

    code output

    关于arrays - json:无法将数组解码为结构类型的 Go 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59698933/

    相关文章:

    c++ - 写作 void fun(int *tab);和 void fun(int tab[]) 是一样的吗?

    调用使用指针接收数组的函数

    python - 根据 Google Cloud Bigtable 中的唯一 ID 选择 JSON 对象

    go - Go中的光标键终端输入

    elasticsearch - 在 google go 中使用 olivere/elastic 通过 ElasticSearch 中的查询更新记录

    c++ - 将 '_' 更改为 ' ' 根本不起作用

    java - 如何将 ASCII 转换为字符串

    javascript - 在mapbox-gl中按部分字符串设置过滤器

    c# - 理论上可以从 JSON 文档生成物理数据库模式吗?

    go - 如何在 Golang Beego 中删除重复的 ORM 实例化