自定义Json Marshaling

时间:2017-04-01 18:33:58

标签: json go

我有一个第三方json api与go合作。
它有一些端点将数据作为键值返回 例如,json用于状态:

{
  "result": {
    "0": "done",
    "1": "incomplete",
    "2": "completed",
    ....
  }
}

因此,当您看到它不是数组时,它就是一个对象 是否有可能将这种json编组为像

这样的对象数组
type Status struct {
    Id int
    Status string
}

不使用其他结构

type StatusReposne struct {
    Result map[string]string `json:"result"`
}

和提取值的代码?

1 个答案:

答案 0 :(得分:2)

正如@mkopriva在评论中指出的那样,一些额外的工作是不可能的。此代码确实提供了向/从Status切片发送/解组数据的方法:

func main() {
    sr := new(StatusReposne)

    json.Unmarshal([]byte(input), sr)
    fmt.Printf("%+v\n", sr)

    js, _ := json.Marshal(sr)
    fmt.Printf("%s\n", js)
}

type StatusReposne struct {
    Result []Status `json:"result"`
}

type Status struct {
    Id     int
    Status string
}

func (x *StatusReposne) MarshalJSON() ([]byte, error) {
    var buffer struct {
        Result map[string]string `json:"result"`
    }
    buffer.Result = make(map[string]string)
    for _, v := range x.Result {
        buffer.Result[strconv.Itoa(v.Id)] = v.Status
    }
    return json.Marshal(&buffer)
}

func (x *StatusReposne) UnmarshalJSON(b []byte) error {
    var buffer struct {
        Result map[string]string `json:"result"`
    }
    buffer.Result = make(map[string]string)
    json.Unmarshal(b, &buffer)
    for k, v := range buffer.Result {
        k, _ := strconv.Atoi(k)
        x.Result = append(x.Result, Status{Id: k, Status: v})
    }
    return nil
}

var input = `{
  "result": {
    "0": "done",
    "1": "incomplete",
    "2": "completed"
  }
}`