【问题标题】:Decode JSON with unknown structure解码具有未知结构的 JSON
【发布时间】:2017-03-18 16:16:57
【问题描述】:

我想得到一个代表这样一个 json 的字符串:

{ "votes": { "option_A": "3" } }

并在其中包含一个“计数”键,因此它的结尾如下:

{ "votes": { "option_A": "3" }, "count": "1" }

这就是为什么我打算将它转换为 json 以便我可以添加计数然后 再次使它成为一个字符串。 问题是我不知道它的结构 JSON,所以我不能使用json.Unmarshal(in, &myStruct),因为那个结构 变化。我该怎么做?

【问题讨论】:

  • 在 myStruct 中,注释变量 count 如果不存在则省略。在变量 json:",omitempty" 前面添加这个
  • 我没有 MyStruct 的定义,因为它绝对可以是任何东西。我只需要将该计数键包含到字符串所代表的任何 json 中。但是感谢您的评论。

标签: json go


【解决方案1】:
package main

import "encoding/json"

func main() {
    in := []byte(`{ "votes": { "option_A": "3" } }`)
    var raw map[string]interface{}
    if err := json.Unmarshal(in, &raw); err != nil {
        panic(err)
    }
    raw["count"] = 1
    out, err := json.Marshal(raw)
    if err != nil {
        panic(err)
    }
    println(string(out))
}

https://play.golang.org/p/o8ZwvgsQmoO

【讨论】:

  • 优雅!并且易于理解
  • 如果你在 json 的 Unmarshall 调用中添加错误处理就好了!
【解决方案2】:

你真的只需要一个结构,正如 cmets 中提到的那样,字段上的正确注释将产生所需的结果。 JSON 不是一种非常多变的数据格式,它定义明确,任何一段 json,无论对您来说多么复杂和混乱,都可以通过模式和 Go 中的对象以 100% 的准确性相当容易地表示,并且大多数其他 OO 编程语言。这是一个例子;

package main

import (
    "fmt"
    "encoding/json"
)

type Data struct {
    Votes *Votes `json:"votes"`
    Count string `json:"count,omitempty"`
}

type Votes struct {
    OptionA string `json:"option_A"`
}

func main() {
    s := `{ "votes": { "option_A": "3" } }`
    data := &Data{
        Votes: &Votes{},
    }
    err := json.Unmarshal([]byte(s), data)
    fmt.Println(err)
    fmt.Println(data.Votes)
    s2, _ := json.Marshal(data)
    fmt.Println(string(s2))
    data.Count = "2"
    s3, _ := json.Marshal(data)
    fmt.Println(string(s3))
}

https://play.golang.org/p/ScuxESTW5i

根据您最近的评论,您可以通过使用interface{} 来表示除计数之外的数据,使计数成为字符串并将其余的blob 推入interface{},它基本上可以接受任何东西。话虽如此,Go 是一种具有相当严格类型系统的静态类型语言,并且重申一下,您的 cmets 声明“它可以是任何东西”是不正确的。 JSON 不能是任何东西。对于任何一段 JSON,都有模式,一个模式可以定义 JSON 的许多变体。我建议您花时间了解数据的结构,而不是在无法定义的概念下将某些东西拼凑在一起,因为它绝对可以并且对于知道自己在做什么的人来说可能很容易。

【讨论】:

  • 旁注:只有结构中大写的属性才会包含在 JSON 中。编组器将忽略私有属性
  • 谢谢,它也对我有用:` b, err := ioutil.ReadFile(reportPath) bAstring := string(b[:]) println(bAstring) log.Debug(err ) data := e2e.E2eTask{} error := json.Unmarshal([]byte(bAstring), &data ) log.Debug(error) fmt.Println("数据状态:" + data.Status)` .
猜你喜欢
  • 2017-04-11
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多