Home > database >  Output json with os.stdout.write and a new line?
Output json with os.stdout.write and a new line?

Time:03-17

new to golang here. I wanted to simply output some json to stdout for debug purposes. I think I'm going about this all wrong. Here is what I have:

type SomeObject struct {
  Thing1 string
  Thing2 string
  Thing3 otherStruct
}

...

someObject = &SomeObject{
  Thing1: "hello",
  Thing2: "world",
  ...
}
someObjectLogEntry, err := json.Marshal(someObject)
if err != nil {
    fmt.Println("error:", err)
}
os.Stdout.Write(someObjectLogEntry)

When I run this, it outputs the json as one line, however my service also has a heartbeat going and so the two coincide and output both things in the same line, something like:

{/// All that json content }[GIN] 2022/03/16 - 02:07:16 | 200 | 1.16µs | 127.0.0.1 | GET "/heartbeat"

What's the correct way to do what I'm doing (simply constructing a json object and outputting it)? If i do fmt.println it will then print out the byte code. Thanks!

CodePudding user response:

You need to output a line feed or newline (\n) after the JSON. The simplest approach is probably using fmt.Printf e.g. (playground)

type SomeObject struct {
    Thing1 string
    Thing2 string
}
someObject := &SomeObject{
    Thing1: "hello",
    Thing2: "world",
}
someObjectLogEntry, err := json.Marshal(someObject)
if err != nil {
    fmt.Println("error:", err)
}
fmt.Printf("%s\n", someObjectLogEntry)
os.Stdout.Write([]byte("something else\n"))

CodePudding user response:

The typical way to achieve this while using the Printf function from the fmt package is by including a newline character \n in the format string. You don’t necessarily need to write the data to standard output, because Printf does that for you.

Another option is to use the Println function from the fmt package which formats using the default formats for its operands writes to standard output. It’s necessary to convert your JSON bytes to string while using Println. Note that, spaces are always added between the operands and a newline is appended while using Println.

The reason that you see individual byte values while using fmt.Println is because a byte slice is printed out as uninterpreted bytes of the string or slice — the byte slice can contain anything at all, not just printable characters. On the other hand, os.Stdout.Write writes the byte slice to standard out and your terminal renders them properly because they are printable characters.

CodePudding user response:

The cleanest approach is to use json.Encoder to os.Stdout.

json.Encoder already appends a newline to each message written and is more efficient than using fmt with json bytes.

You can re-use the json encoder instead of calling json.Marshal then some type of separate write for each message.

import (
   "os"
   "encoding/json"
)

type SomeObject struct {
  Thing1 string
  Thing2 string
  Thing3 otherStruct
}

...

encoder := json.NewEncoder(os.Stdout)

someObject = &SomeObject{
  Thing1: "hello",
  Thing2: "world",
  ...
}

if err := encoder.Encode(&someObject); err != nil {
    // handle error
}


  • Related