Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically add a type field to JSON in Go?

Tags:

How to add a type field automatically to every serialized JSON in Go?

For example, in this code:

type Literal struct {
  Value interface{} `json:'value'`
  Raw   string      `json:'raw'`
}

type BinaryExpression struct {
  Operator string  `json:"operator"`
  Right    Literal `json:"right"`
  Left     Literal `json:"left"`
}

os.Stdout.Write(json.Marshal(&BinaryExpression{ ... }))

Instead of generating something like:

{
   "operator": "*",
   "left": {
      "value": 6,
      "raw": "6"
   },
   "right": {
      "value": 7,
      "raw": "7"
   }
}

I'd like to generate this:

{
   "type": "BinaryExpression",
   "operator": "*",
   "left": {
      "type": "Literal",
      "value": 6,
      "raw": "6"
   },
   "right": {
      "type": "Literal",
      "value": 7,
      "raw": "7"
   }
}
like image 335
Alon Gubkin Avatar asked Jun 03 '16 10:06

Alon Gubkin


1 Answers

You can override the MarshalJSON function for your struct to inject the type into an auxiliary struct which then gets returned.

package main

import (
    "encoding/json"
    "os"
)

type Literal struct {
    Value interface{} `json:'value'`
    Raw   string      `json:'raw'`
}

func (l *Literal) MarshalJSON() ([]byte, error) {
    type Alias Literal
    return json.Marshal(&struct {
        Type string `json:"type"`
        *Alias
    }{
        Type:  "Literal",
        Alias: (*Alias)(l),
    })
}

type BinaryExpression struct {
    Operator string  `json:"operator"`
    Right    Literal `json:"right"`
    Left     Literal `json:"left"`
}

func (b *BinaryExpression) MarshalJSON() ([]byte, error) {
    type Alias BinaryExpression
    return json.Marshal(&struct {
        Type string `json:"type"`
        *Alias
    }{
        Type:  "BinaryExpression",
        Alias: (*Alias)(b),
    })
}

func main() {
    _ = json.NewEncoder(os.Stdout).Encode(
        &BinaryExpression{
            Operator: "*",
            Right: Literal{
                Value: 6,
                Raw:   "6",
            },
            Left: Literal{
                Value: 7,
                Raw:   "7",
            },
        })
}
like image 53
Christian Witts Avatar answered Sep 28 '22 01:09

Christian Witts