overexchange
overexchange

Reputation: 1

json.Marshal vs Encoder.Encode

In the below code:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type Student struct {
    Firstname, lastname string
    Email               string
    Age                 int
    HeightInMeters      float64
    IsMale              bool
}

func main() {
    john := Student{
        Firstname:      "John",
        lastname:       "Doe",
        Age:            21,
        HeightInMeters: 1.75,
        IsMale:         true,
    }

    johnJSON, _ := json.Marshal(john) // johnJSON is of type []byte
    fmt.Println(string(johnJSON))     // print it in characters

}

johnJSON, _ := json.Marshal(john) is encoding a struct type(john) to []byte.


In the below code:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type Student struct {
    Firstname, lastname string
    Email               string
    Age                 int
    HeightInMeters      float64
    IsMale              bool
}

func main() {
    john := Student{
        Firstname:      "John",
        lastname:       "Doe",
        Age:            21,
        HeightInMeters: 1.75,
        IsMale:         true,
    }

    // johnJSON, _ := json.Marshal(john) // johnJSON is of type []byte
    // fmt.Println(string(johnJSON))     // print it in characters

    // create a buffer to hold JSON data
    buf := new(bytes.Buffer)
    // create JSON encoder for `buf`
    bufEncoder := json.NewEncoder(buf)

    bufEncoder.Encode(john)
    // print contents of the `buf`
    fmt.Println(buf) // calls `buf.String()` method
}

bufEncoder.Encode(john) is marshaling struct type(john) to io.Writer type(buf)


When to use json.Marshal() vs Encoder.Encode()? Because both buf and johnJSON are []byte type

type Buffer struct {
    buf      []byte // contents are the bytes buf[off : len(buf)]
    off      int    // read at &buf[off], write at &buf[len(buf)]
    lastRead readOp // last read operation, so that Unread* can work correctly.
}

Upvotes: 0

Views: 4414

Answers (2)

thwd
thwd

Reputation: 51

There are three differences.

  • The application can set encoding options on the encoder. Examples are SetEscapeHTML and SetIndent. There are no options with the Marshal function.
  • The Marshal function encodes the JSON document to a single []byte that must be in memory. The encoder writes data through to the underlying io.Writer, thus avoiding the need to have the entire encoded document in memory.
  • To support streams of JSON documents, the encoder adds a whitespace byte after each JSON document. See https://play.golang.org/p/Apb5GJeEcQq for the difference. The extra whitespace is ignored by JSON parsers.

If the feature differences between the Marshal function and Encoder type do not dictate a choice between them, then use the one that's most convenient. The Marshal function and Encoder type share most of their implementation and have similar performance. The Marshal function is not a wrapper around the Encoder as claimed in a different answer.

Upvotes: 5

Burak Serdar
Burak Serdar

Reputation: 51652

Marshal (Unmarshal) is a wrapper around Encoder (Decoder). They are mainly convenience functions that provide a convenient interface to the lower level encoder/decoder implementations.

If you need to process JSON streams containing more than one JSON document, or if you need to process a JSON stream without unmarshaling the whole document to an in-memory structure, use decoder. If you have a Reader, you can use Decoder instead of Unmarshal.

Similarly, if you are generating JSON stream without an in-memory structure, or are writing multiple JSON documents into a stream, use Encoder. If you have a Writer, you can use an encoder without first unmarshaling to a byte array and then writing it.

Upvotes: 3

Related Questions