tidwall / sjson

Set JSON values very quickly in Go
MIT License
2.4k stars 165 forks source link

Question: Empty Initialised Array vs Uninitialised Array #39

Closed dataBaseError closed 4 years ago

dataBaseError commented 4 years ago

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}
tidwall commented 4 years ago

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

dataBaseError commented 4 years ago

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