tidwall / sjson

Set JSON values very quickly in Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: Empty Initialised Array vs Uninitialised Array

dataBaseError opened this issue · comments

When an slice is not initialised empty (e.g. var list []string) the value is set as null instead of [].
However if we initialised the slice (e.g. var list := []string{}) the value is set as []

Is this the expected behaviour or a bug? It is inconsistent with the encoding/json which in both cases will produce [].

Below is a simple program that highlights this issue including the output on my system. The output test3 is the one of note, where the array is output as null.

package main

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/sjson"
)

func handleError(err error) {
	if err != nil {
		panic(err)
	}
}

type Example struct {
	Data []string `json:"data"`
}

func main() {

	data := Example{
		Data: []string{"a", "b", "c"},
	}
	raw, err := json.Marshal(data)
	handleError(err)

	fmt.Println("raw: ", string(raw))

	data = Example{
		Data: []string{},
	}
	raw, err = json.Marshal(data)
	handleError(err)

	fmt.Println("raw: ", string(raw))

	sDataArray := []string{"a", "b", "c"}
	test1, err := sjson.SetBytes(raw, "sdata_array", sDataArray)
	handleError(err)

	fmt.Println("test1: ", string(test1))

	sDataArray = []string{}
	test2, err := sjson.SetBytes(raw, "sdata_array", sDataArray)
	handleError(err)

	fmt.Println("test2: ", string(test2))

	var sDataArrayNil []string
	test3, err := sjson.SetBytes(raw, "sdata_array", sDataArrayNil)
	handleError(err)

	fmt.Println("test3: ", string(test3))
}

Output:

raw:  {"data":["a","b","c"]}
raw:  {"data":[]}
test1:  {"data":[],"sdata_array":["a","b","c"]}
test2:  {"data":[],"sdata_array":[]}
test3:  {"data":[],"sdata_array":null}

With the first two examples:

data = Example{
    Data: []string{"a", "b", "c"},
}

and

data = Example{
    Data: []string{},
}

The builtin encoding/json is interpreting these as non-nil slices and thus writing out [] instead of null.

If you use:

data = Example{
    Data: null,
}
data = Example{}

You'll see that the builting Go json encoder and sjson both work the same.

Here's another example

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

My mistake, I didn't correctly initialise my example using the native library. Thank you for correcting me.