将json值解组为[]字节,其中字符串有时可以转义为json

时间:2017-12-14 21:16:38

标签: json go

我有一个看起来像这样的json响应

{
  "eventId":"fbf4a1a1-b4a3-4dfe-a01f-ec52c34e16e4",
  "eventType":"event-type",
  "eventNumber":0,
  "data":"{\n  \"a\": \"1\"\n}",
  "metaData":"{\n  \"yes\": \"no\"\n}",
  "streamId":"test",
  "isJson":true,
  "isMetaData":true,
  "isLinkMetaData":false,
  "positionEventNumber":0,
  "positionStreamId":"test",
  "title":"0@test",
  "id":"http://localhost:2113/streams/test/0",
  "updated":"2017-12-14T05:09:58.816079Z"
}

数据的键值对,metaData有时可能是json编码,也可能不是。

我想将这些值解码为像这样的字节数组。

// Event represent an event to be stored.
type Event struct {
    Data      []byte    `json:"data"`
    Metadata  []byte    `json:"metaData"`
}

但是当我尝试解组json对象时,我收到以下错误:

illegal base64 data at input byte 0

我在这里做错了什么?

如果我将数据和metaData解码为字符串,它可以正常工作,但我不想使用字符串。

2 个答案:

答案 0 :(得分:7)

您正在寻找json.RawMessage类型

它只是一个专门的[]字节,您可以根据需要使用它。

type Event struct {
    Data      json.RawMessage    `json:"data"`
    Metadata  json.RawMessage    `json:"metaData"`
}

然后您可以通过[]byte(e.Data)

将其视为文字[]字节

以下是使用示例on play

package main

import (
    "encoding/json"
    "fmt"
)

var RAW = []byte(`
{
  "eventId":"fbf4a1a1-b4a3-4dfe-a01f-ec52c34e16e4",
  "eventType":"event-type",
  "eventNumber":0,
  "data":"{\n  \"a\": \"1\"\n}",
  "metaData":"{\n  \"yes\": \"no\"\n}",
  "streamId":"test",
  "isJson":true,
  "isMetaData":true,
  "isLinkMetaData":false,
  "positionEventNumber":0,
  "positionStreamId":"test",
  "title":"0@test",
  "id":"http://localhost:2113/streams/test/0",
  "updated":"2017-12-14T05:09:58.816079Z"
}
`)

type Event struct {
    Data     json.RawMessage `json:"data"`
    Metadata json.RawMessage `json:"metaData"`
}

func main() {
    var e Event
    err := json.Unmarshal(RAW, &e)
    fmt.Printf("%v -- %+v\n", err, e)
    b, err := json.Marshal(e)
    fmt.Printf("%v -- %s\n", err, b)
}

答案 1 :(得分:1)

我创建了一个实现TextUnmarshaler和TextMarshaler接口的类型。如果类型没有实现MarshalJSON和UnmarshalJSON方法,json解码器会查找此内容。

type RawData []byte

func (r RawData) MarshalText() (text []byte, err error) {
    return r[:], nil
}

func (r *RawData) UnmarshalText(text []byte) error {
    *r = text[:]

    return nil
}

// Event represent an event to be stored.
type Event struct {
    Data      RawData   `json:"data,omitempty"`
    Metadata  RawData   `json:"metaData,omitempty"`

}

我需要这个,因为有时数据或元数据不会以字符串形式进行json编码,但也可能是协议缓冲区等其他格式。