在json.Marshal()中指定struct格式

时间:2014-10-02 21:33:41

标签: json go format marshalling

我有以下结构,用于与API通信:

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

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

我在发送之前使用json.MarshalIndent()将我的结构转换为json。这给了我类似的东西:

{
       "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"
               }
       ]
}

我希望在编组之前格式化value值(因为它的类型为interface{}我需要根据值类型格式化它)。

我遇到的第一个解决方案是创建(Object) encode() string函数或其他东西,迭代[]Property格式化值,并分别编组每个属性,然后使用{{1重构对象而不是[]string,然后编组对象。

有没有内置的方法呢?如果没有,是否有任何惯用的方式呢?

1 个答案:

答案 0 :(得分:1)

JSON编码器根据值的实际类型编组接口{}值。您可以通过多种方式覆盖默认编码。

第一种是围绕值创建一个包装器,以控制使用Marshaler interface对它们进行编码的方式。这是一个改变整数编码方式的包装器:

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)
  }
}

像这样使用:

prop.Value = Value{45}

playground

第二种方法是在Property类型上实现Marshaler以覆盖所有属性的封送方式,包括Value字段。

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
}

playground