Putting multiple JSON objects in a JSON array

Hello folks,

I’m new to Go so please forgive me if I used the wrong terminology somewhere or if I did something wrong in general. I’m happy to learn how to do things in a better way, so please feel free to point out any mistakes.

I declared a struct like this:

type Measurement struct {
	Id            int        `json:"id"`
	Time          time.Time  `json:"time"`
	Voltage       float32    `json:"voltage"`
	Current       float32    `json:"current"`
	Power         float32    `json:"power"`
	PowerFactor   float32	 `json:"powerfactor"`
}

Which I can easily send over HTTP like this:

func MeasurementShow(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	
	var measurement Measurement
	// Get a Measurement object from somewhere ...

	err := json.NewEncoder(w).Encode(measurement)

	if err != nil {
		panic(err)
	}
}

The received JSON looks like this:

{"id":4,"time":"0001-01-01T00:00:00Z","voltage":233.1,"current":9.2,"power":0,"powerfactor":0}

What I’d like to do now is putting multiple of these JSON encoded measurements into one JSON array and sending that array. However, I fail to understand how I can encode a slice of Measurementobjects as JSON objects into a JSON array. I played around with json.Marshal() but I ended up with something that looked like a base64 encoded byte array (slice?) instead:

var measurements []Measurement

// Get some Measurements from somewhere ...

var jsonArray [][]byte
for _, measurement := range measurements {
	jsonObject, _ := json.Marshal(measurement)
	jsonArray = append(jsonArray, jsonObject)
}

measurement := RepoFindMeasurement(measurementId)
if measurement.Id > 0 {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(jsonArray); err != nil {
		panic(err)
	}
	return
}

Which gave me:

["eyJpZCI6NCwidGltZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIiwidm9sdGFnZSI6MjMzLjEsImN1cnJlbnQiOjkuMiwicG93ZXIiOjAsInBvd2VyZmFjdG9yIjowfQ==","eyJpZCI6MywidGltZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIiwidm9sdGFnZSI6MjI5LjMsImN1cnJlbnQiOjE3LjIsInBvd2VyIjowLCJwb3dlcmZhY3RvciI6MH0=","eyJpZCI6MiwidGltZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDBaIiwidm9sdGFnZSI6MjMxLjQsImN1cnJlbnQiOjE0LjksInBvd2VyIjowLCJwb3dlcmZhY3RvciI6MH0="]

While I expected something like this:

[
	{"id":4,"time":"0001-01-01T00:00:00Z","voltage":233.1,"current":8.7,"power":0,"powerfactor":0},
	{"id":4,"time":"0001-01-01T00:00:00Z","voltage":234.5,"current":9.1,"power":0,"powerfactor":0},
	{"id":4,"time":"0001-01-01T00:00:00Z","voltage":235.7,"current":9.9,"power":0,"powerfactor":0},
	{"id":4,"time":"0001-01-01T00:00:00Z","voltage":234.3,"current":9.2,"power":0,"powerfactor":0}
]

Can anybody explain to me what I have to do in order to encode multiple Measurement objects in a JSON array prior to sending it over HTTP?

You can just json.Marshal your []Measurement and get the result you expect. No loop required.

2 Likes

Oh… well, that was easy :smiley:
Thank you very much for your help. Much appreciated!

If I may ask: What is the difference between json.Encode() and json.Marshal()?

Encode writes a non-indented newline-delimited object/array to the Writer in question. Marshal/MarshalIndent returns the marshalled object as a byte slice. Here’s an example I didn’t have time to put in the initial reply:

https://play.golang.org/p/gFnD19DTj2

1 Like

Thank you for the explanation and the example :slight_smile:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.