【问题标题】:Marshal/Unmarshal int typeMarshal/Unmarshal int 类型
【发布时间】:2018-10-15 16:09:25
【问题描述】:

我使用int 类型来表示枚举。当我将其编组为 JSON、AFAIK 时,我想将其转换为字符串,我应该实现 UnmarshalJSONMarshalJSON,但它抱怨:

marshal 错误:json:错误调用 MarshalJSON 的类型 main.trxStatus:寻找开头的无效字符“b” 值 JSON 输入的意外结束

编组时。然后我将引号添加到编组字符串中:

func (s trxStatus) MarshalJSON() ([]byte, error) {
    return []byte("\"" + s.String() + "\""), nil
}

Marshal 现在可以工作,但它不能从编组字节流中正确地Unmarshal

package main

import (
    "encoding/json"
    "fmt"
)

type trxStatus int

type test struct {
    S trxStatus
    A string
}

const (
    buySubmitted trxStatus = iota
    buyFilled
    sellSubmiited
    sellFilled
    finished
)

var ss = [...]string{"buySubmitted", "buyFilled", "sellSubmiited", "sellFilled", "Finished"}

func (s *trxStatus) UnmarshalJSON(bytes []byte) error {
    status := string(bytes)
    // unknown
    for i, v := range ss {
        if v == status {
            tttt := trxStatus(i)
            *s = tttt
            break
        }
    }
    return nil
}

func (s trxStatus) MarshalJSON() ([]byte, error) {
    return []byte(s.String()), nil
}

func (s trxStatus) String() string {

    if s < buySubmitted || s > finished {
        return "Unknown"
    }

    return ss[s]
}

func main() {
    s := test{S: buyFilled, A: "hello"}
    j, err := json.Marshal(s)
    if err != nil {
        fmt.Printf("marshal error: %v", err)
    }
    var tt test
    fmt.Println(json.Unmarshal(j, &tt))
    fmt.Println(tt)
}

【问题讨论】:

  • 1.检查 json.Marshal 的错误,2. 导出测试的字段,否则封送将不起作用。 3. 您的 MarshalJSON 不返回 json 字符串,即缺少引号。 4.woking example
  • @mkopriva 感谢您的提示,请参阅我的编辑。
  • 这是更新评论中提到的缺失引号。
  • 我已经添加了引号,但是 Unmarshal 不起作用
  • 请注意,手动构建 JSON 字符串通常是有风险的,因为转义很棘手。 MarshalJSON 的更健壮的实现是return json.Marshal(s.String())

标签: json go marshalling


【解决方案1】:

在编写自定义 Marshaler 和 Unmarshaler 实现时,请确保包含或修剪 json 字符串周围的双引号。

func (s *trxStatus) UnmarshalJSON(bytes []byte) error {
    status := string(bytes)
    if n := len(status); n > 1 && status[0] == '"' && status[n-1] == '"' {
        status = status[1:n-1] // trim surrounding quotes
    }
    // unknown
    for i, v := range ss {
        if v == status {
            tttt := trxStatus(i)
            *s = tttt
            break
        }
    }
    return nil
}

func (s trxStatus) MarshalJSON() ([]byte, error) {
    return []byte(`"` + s.String() + `"`), nil
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多