解码具有未知结构的 JSON 数据。

huangapple go评论79阅读模式
英文:

Decode JSON with unknown structure

问题

我想获得一个表示如下JSON的字符串:

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

并在其中包含一个"count"键,使其最终变成这样:

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

这就是为什么我计划将其转换为JSON,这样我就可以添加计数,然后再将其转换为字符串。问题是我不知道该JSON的结构,所以我无法使用json.Unmarshal(in, &myStruct),因为该结构是可变的。我该如何做到这一点?

英文:

I want to get a string that represents a json like this one:

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

and include a "count" key in it so it ends like this:

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

This is why I planned to convert it to json so I could add the count and then
make it a string again. The problem is I don't know the structure of that
JSON
, so I can't use json.Unmarshal(in, &myStruct) because that struct
varies. How can I do this?

答案1

得分: 97

解码为map[string]interface{}

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

英文:

Unmarshal into map[string]interface{}:

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

答案2

得分: 71

你只需要一个结构体,如评论中所提到的,正确的字段注释将产生所需的结果。JSON不是一种非常多变的数据格式,它是明确定义的,无论JSON有多么复杂和令人困惑,都可以相对容易地以及100%准确地通过模式和Go和大多数其他面向对象编程语言中的对象来表示。这里有一个例子:

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))
}

根据您最近的评论,您可以使用interface{}来表示除计数之外的数据,将计数作为字符串,并将其余的数据塞入interface{}中,它将接受几乎任何内容。也就是说,Go是一种具有相当严格类型系统的静态类型语言,重申一下,您的评论中的“它可以是任何东西”是不正确的。JSON不能是任何东西。对于任何JSON,都有一个模式,一个模式可以定义许多许多JSON的变体。我建议您花时间了解数据的结构,而不是在认为它无法定义时将其拼凑在一起,因为它绝对可以定义,并且对于知道自己在做什么的人来说可能非常容易。

英文:

You really just need a single struct, and as mentioned in the comments the correct annotations on the field will yield the desired results. JSON is not some extremely variant data format, it is well defined and any piece of json, no matter how complicated and confusing it might be to you can be represented fairly easily and with 100% accuracy both by a schema and in objects in Go and most other OO programming languages. Here's an example;

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

Based on your most recent comment you could address that by using an interface{} to represent data besides the count, making the count a string and having the rest of the blob shoved into the interface{} which will accept essentially anything. That being said, Go is a statically typed language with a fairly strict type system and to reiterate, your comments stating 'it can be anything' are not true. JSON cannot be anything. For any piece of JSON there is schema and a single schema can define many many variations of JSON. I advise you take the time to understand the structure of your data rather than hacking something together under the notion that it cannot be defined when it absolutely can and is probably quite easy for someone who knows what they're doing.

huangapple
  • 本文由 发表于 2016年11月5日 02:11:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/40429296.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定