dongshang1979 2014-10-02 21:33
浏览 303
已采纳

在json.Marshal()中指定结构格式

I have the following structs, which I use to communicate with an API:

type Object struct {
    Id         uint64
    Type       string
    Class      string
    Properties []Property
}

type Property struct {
    Name     string
    DataType string
    Value    interface{}
}

And I use json.MarshalIndent() to convert my struct into a json before sending it. this gives me something like:

{
       "Id": 15,
       "Type": "Node",
       "Class": "Persona",
       "Properties": [
               {
                       "Name": "Nombre",
                       "DataType": "text",
                       "Value": "Oso"
               },
               {
                       "Name": "Edad",
                       "DataType": "int",
                       "Value": 45
               },
               {
                       "Name": "Fecha de Naciemiento",
                       "DataType": "date",
                       "Value": "1989-09-27T05:30:08-06:00"
               }
       ]
}

I want to format the value value (because it is of type interface{} I need to format it depending on the value type) of the struct Property before marshaling it.

The first solution that occurred to me was to create a (Object) encode() string function or something, that iterates through []Property formatting the values, and marshaling each property separately, then reconstructing the Object with an []string instead of the []Property and then marshaling the object.

Is there any built-in way of doing this? If not, is there any idiomatic way of doing it?

  • 写回答

1条回答 默认 最新

  • drblhw5731 2014-10-02 21:44
    关注

    The JSON encoder marshals interface{} values according to the actual type of the value. You can override the default encoding in a couple of ways.

    The first is to create a wrapper around values to control how they are encoded using the Marshaler interface. Here's a wrapper that changes how integers are encoded:

    type Value struct{ Value interface{} }
    
    func (v Value) MarshalJSON() ([]byte, error) {
      switch v := v.Value.(type) {
      case int:
        return []byte(fmt.Sprintf("\"#%d\"", v)), nil
      default:
        return json.Marshal(v)
      }
    }
    

    Use it like this:

    prop.Value = Value{45}
    

    <kbd>playground</kbd>

    A second approach is to implement the Marshaler on the Property type to override how all of the property is marshaled including the Value field.

    func (p Property) MarshalJSON() ([]byte, error) {
      var buf bytes.Buffer
      buf.WriteString(`{"Name":`)
      d, err := json.Marshal(p.Name)
      if err != nil {
        return nil, err
      }
      buf.Write(d)
      buf.WriteString(`,"DataType":`)
      d, err = json.Marshal(p.DataType)
      if err != nil {
        return nil, err
      }
      buf.Write(d)
      buf.WriteString(`, "Value":`)
      switch v := p.Value.(type) {
      case int:
        fmt.Fprintf(&buf, "\"#%d\"", v)
      default:
        d, err := json.Marshal(v)
        if err != nil {
            return nil, err
        }
        buf.Write(d)
      }
      buf.WriteString("}")
      return buf.Bytes(), nil
    }
    

    <kbd>playground</kbd>

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊
  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题
  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题