【问题标题】:Parse Error from Converting Json String to Struct将 Json 字符串转换为结构时解析错误
【发布时间】:2020-04-15 11:47:13
【问题描述】:

我无法解析我发送游乐场链接的 json 值 有什么想法吗?这是链接和代码

https://play.golang.org/p/qhZpS_-618s

package main

import (
    "encoding/json"
    "fmt"
    //mapstructure "github.com/mitchellh/mapstructure"

)

type presence struct{
    id string 
    m_type string 
    deny string 
}
type jsonHandler struct {
    name string 
    dat map[string]interface{}

}   

func main() {
    s := `["Presence",{"id":"905356870666@c.us","type":"unavailable","deny":true}]`
    data := jsonHandler{}
    json.Unmarshal([]byte(s), &data)
    fmt.Printf("Operation: %s", data.name)


}

输出: 手术: 程序已退出。

【问题讨论】:

标签: json parsing go


【解决方案1】:

试试这个:https://play.golang.com/p/UICf_uNNFdC

为了提高代码的可读性,我发表了很多评论。请务必正确处理错误并删除调试打印。

package main

import (
    "encoding/json"
    "log"
    "strings"
)

type Presence struct {
    Presence string
    ID       string `json:"id"`
    Type     string `json:"type"`
    Deny     bool   `json:"deny"`
}

type JsonHandler struct {
    Name string   `json:"name"`
    Dat  Presence `json:"dat"`
}

func main() {
    var (
        // Used for unmarshal a given json
        packedData []json.RawMessage
        err        error
        // Data that does not have a related json key
        name []byte
        // Used for extract the raw data that will be unmarshalled into the Presence struct
        temp []byte
        // Nested json
        jsonPresence Presence
        handler      JsonHandler
    )

    s := `["Presence",{"id":"905356870666@c.us","type":"unavailable","deny":true}]`

    log.Println("Dealing with -> " + s)

    // Unmarshall into a raw json message
    err = json.Unmarshal([]byte(s), &packedData)
    if err != nil {
        panic(err)
    }

    // Extract the presence
    log.Println("Presence: ", string(packedData[0]))
    // Extract the nested json
    log.Println("Packed: ", string(packedData[1]))

    // NOTE: 0 refers to the first value of the JSON
    name, err = packedData[0].MarshalJSON()
    if err != nil {
        panic(err)
    }
    log.Println("Value that does not have a key: " + string(name))
    handler.Name = strings.Replace(string(name), "\"", "", -1)

    // NOTE: 1 refers to the second value of the JSON, the entire JSON
    // Unmarshal the nested Json into byte
    temp, err = packedData[1].MarshalJSON()
    if err != nil {
        panic(err)
    }

    // Unmarshal the raw byte into the struct
    err = json.Unmarshal(temp, &jsonPresence)
    if err != nil {
        panic(err)
    }

    log.Println("ID:", jsonPresence.ID)
    log.Println("Type:", jsonPresence.Type)
    log.Println("Deny:", jsonPresence.Deny)

    handler.Dat = jsonPresence

    log.Println("Data unmarshalled: ", handler)
}

【讨论】:

  • 我们只是简单地解析["Presence",{"id":"905356870666@c.us","type":"unavailable","deny":true}] bro 这些代码对于这个json来说太复杂和太多了......必须有一个捷径(2,3行代码)通过经历7年的软件开发人员
【解决方案2】:

去游乐场链接:https://play.golang.org/p/qe0jyFVNTH1

这里没有什么问题:

1. Json包不能引用未导出的结构元素。所以请在下面的sn-p中使用Deny而不是deny。这适用于结构内声明的所有变量

2. json fields 标签不正确。例如mapstructure:"id" 应该是json:"id"

3.要解析的json包含两个不同的元素,即字符串“Presence”和嵌套的json对象。不能作为单个元素解析。最好声明“Presence”为key,嵌套json为value。

4.deny变量应该是bool而不是string

【讨论】:

  • 好吧,我想解析 ["Presence",{"id":"905356870666@c.us","type":"unavailable","deny":true}] 不是你提供的对我来说 {"Presence":{"id":"905356870666@c.us","type":"unavailable","deny":true}} 所以你的评论对我没有任何意义,因为我收到了这个 json从whatsapp套接字请根据json数组回答问题:[“Presence”,{“id”:“905356870666@c.us”,“type”:“unavailable”,“deny”:true}]
  • @user3236289 您的 Json 不是有效的 Json。也回答是真的。要解组 Json,请导出您的结构字段。所以使用大写字母。也不要使用“地图结构”。以及为什么“jsonHandler”结构具有名称和数据字段。它们与 Json 数据无关。也许你应该深入解释一下。
  • 我的 json 是正确的,不是错误的格式。它来自 whatsapp 套接字好吗?这里解析了我的 json dropbox.com/s/0asnrkkinhfh2ke/…
  • @user3236289 根据您的用例,任何直接方法都不适用于这种情况。您必须将数据解析为 json.RawMessage(如 @alessiosavi 所示)或接口{}然后实现自定义逻辑。使用自定义解组器也是一个不错的选择。请阅读 Marko Mikulicic 撰写的这篇文章link。您将对可能的解决方案有一定的了解。
【解决方案3】:

哇,只添加这些代码就解决了问题

Here Go Lang 链接:https://play.golang.org/p/doHNWK58Cae

func (n *JsonHandler) UnmarshalJSON(buf []byte) error {
    tmp := []interface{}{&n.Name, &n.Dat}
    wantLen := len(tmp)
    if err := json.Unmarshal(buf, &tmp); err != nil {
        return err
    }
    if g, e := len(tmp), wantLen; g != e {
        return fmt.Errorf("wrong number of fields in Notification: %d != %d", g, e)
    }
    return nil
}

【讨论】:

  • +1 非常干净!您是否测试过这两种解决方案的性能?我认为这个在速度方面比我的解决方案更优化。
猜你喜欢
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多