将嵌套对象的json.Unmarshal转换为字符串或[]byte。

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

json.Unmarshal nested object into string or []byte

问题

我正在尝试解析一些 JSON 数据,以便将嵌套对象视为 string[]byte,而不是解析它。

所以我想要得到以下结果:

{
    "id"  : 15,
    "foo" : { "foo": 123, "bar": "baz" }
}

解析为:

type Bar struct {
    ID  int64  `json:"id"`
    Foo []byte `json:"foo"`
}

我得到了以下错误:

json: cannot unmarshal object into Go value of type []uint8

playground 示例

英文:

I'm trying to Unmarshal some json so that a nested object does not get parsed but just treated as a string or []byte.

So I want to get the following:

{
    "id"  : 15,
    "foo" : { "foo": 123, "bar": "baz" }
}

Unmarshaled into:

type Bar struct {
    ID  int64  `json:"id"`
    Foo []byte `json:"foo"`
}

I get the following error:

json: cannot unmarshal object into Go value of type []uint8

playground demo

答案1

得分: 56

我认为你正在寻找的是encoding/json包中的RawMessage类型。

文档中说明:

type RawMessage []byte

RawMessage是一个原始编码的JSON对象。它实现了Marshaler和Unmarshaler接口,可以用于延迟JSON解码或预先计算JSON编码。

以下是使用RawMessage的工作示例:

package main

import (
	"encoding/json"
	"fmt"
)

var jsonStr = []byte(`{
    "id"  : 15,
    "foo" : { "foo": 123, "bar": "baz" }
}`)

type Bar struct {
	Id  int64           `json:"id"`
	Foo json.RawMessage `json:"foo"`
}

func main() {
	var bar Bar

	err := json.Unmarshal(jsonStr, &bar)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", bar)
}

输出结果:

{Id:15 Foo:[123 32 34 102 111 111 34 58 32 49 50 51 44 32 34 98 97 114 34 58 32 34 98 97 122 34 32 125]}

Playground

英文:

I think what you are looking for is the RawMessage type in the encoding/json package.

The documentation states:

>type RawMessage []byte
>
RawMessage is a raw encoded JSON object. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.

Here is a working example of using RawMessage:

package main

import (
	"encoding/json"
	"fmt"
)

var jsonStr = []byte(`{
    "id"  : 15,
    "foo" : { "foo": 123, "bar": "baz" }
}`)

type Bar struct {
	Id  int64           `json:"id"`
	Foo json.RawMessage `json:"foo"`
}

func main() {
	var bar Bar

	err := json.Unmarshal(jsonStr, &bar)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", bar)
}

Output:

> {Id:15 Foo:[123 32 34 102 111 111 34 58 32 49 50 51 44 32 34 98 97 114 34 58 32 34 98 97 122 34 32 125]}

Playground

答案2

得分: 3

Foo类型是一个map[string]string,所以要正确定义Foo:

type Bar struct {
    id int64
    Foo map[string]string
}

认为这样会更好。

英文:

The Foo type is a map[string]string so define Foo correctly:

type Bar struct {
    id int64
    Foo map[string]string
}

Think that would work better

答案3

得分: 2

定义一个实现Unmarshaler接口的类型可以让你访问被解析的[]byte

type Prefs []byte

func (p *Prefs) UnmarshalJSON(b []byte) error {
    *p = make(Prefs, len(b))
    copy(*p, b)
    return nil
}

playground演示

英文:

Defining a type which implements the Unmarshaler interface gives you access to the []byte's being parsed.

type Prefs []byte

func (p *Prefs) UnmarshalJSON(b []byte) error {
	*p = make(Prefs, len(b))
	copy(*p, b)
	return nil
}

playground demo

答案4

得分: -1

经过一番调试,我发现在你的游乐场演示中,最大的问题是将 JSON 类型转换为 []byte 类型。为了理解我的意思,可以查看这个游乐场链接:http://play.golang.org/p/M0706KCZbh

如果你运行它,你会注意到类型转换切片和编组切片之间的 []byte 在 'Prefs' 变量周围有所不同。

从结构体编组的 JSON:

[123 34 105 100 34 58 49 53 44 34 112 114 101 102 115 34 58 34 101 121 65 105 90...

类型转换的 []byte:

[123 34 105 100 34 58 49 53 44 34 112 114 101 102 115 34 58 123 34 102 111 111 34...

我已经删除了空格,以尽可能地对齐。从中可以得出的主要结论是,类型转换不会产生与通过 json.Marshal 方法运行数据相同的结果,为了使其工作,你需要一个自定义类型来处理 JSON 包无法识别的反编组。

英文:

After a bit of tinkering I've found that in your playground demo the biggest problem is the typecasting of the json to a []byte. To see what I mean by that, take a look a this playground: http://play.golang.org/p/M0706KCZbh

If you run it, you'll notice the []byte between the typecast slice and the marshaled slice differ around the point of the 'Prefs' variable.

json marshaled from struct

[123 34 105 100 34 58 49 53 44 34 112 114 101 102 115 34 58 34 101 121 65 105 90...

typecast []byte

[123 34 105 100 34 58 49 53 44 34 112 114 101 102 115 34 58 123 34 102 111 111 34...

I've removed white space to try and make it line up as much as possible. The main takeaway from this is that typecasting does not produce the same results as running the data through the json.Marshal method and to make this work you would need a custom type to handle the unmarshaling of what the json package does not recognize.

huangapple
  • 本文由 发表于 2013年11月21日 00:52:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/20101954.html
匿名

发表评论

匿名网友

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

确定