diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4f10a30 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/layeh/gopher-json + +go 1.19 + +require github.com/yuin/gopher-lua v0.0.0-20221210110428-332342483e3f diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b744d95 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/yuin/gopher-lua v0.0.0-20221210110428-332342483e3f h1:wihIB0V/mGpVYrL8I7n/WxVqWnP07CBXZ5uCgxUP1tI= +github.com/yuin/gopher-lua v0.0.0-20221210110428-332342483e3f/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= diff --git a/json.go b/json.go index c34af2d..0ee7117 100644 --- a/json.go +++ b/json.go @@ -3,8 +3,9 @@ package json import ( "encoding/json" "errors" + "fmt" - "github.com/yuin/gopher-lua" + lua "github.com/yuin/gopher-lua" ) // Preload adds json to the given Lua state's package.preload table. After it @@ -56,7 +57,6 @@ func apiEncode(L *lua.LState) int { var ( errNested = errors.New("cannot encode recursively nested tables to JSON") - errSparseArray = errors.New("cannot encode sparse array") errInvalidKeys = errors.New("cannot encode mixed or invalid key types") ) @@ -109,10 +109,11 @@ func (j jsonValue) MarshalJSON() (data []byte, err error) { return } if expectedKey != key { - err = errSparseArray - return + errValue := lua.LString(fmt.Sprintf("[%s] = %s", key.String(), value.String())) + arr = append(arr, jsonValue{errValue, j.visited}) + } else { + arr = append(arr, jsonValue{value, j.visited}) } - arr = append(arr, jsonValue{value, j.visited}) expectedKey++ key, value = converted.Next(key) } @@ -131,6 +132,9 @@ func (j jsonValue) MarshalJSON() (data []byte, err error) { default: err = errInvalidKeys } + case *lua.LUserData: + data, err = json.Marshal(nil) + return default: err = invalidTypeError(j.LValue.Type()) } diff --git a/json_test.go b/json_test.go index fbd627d..a164bc9 100644 --- a/json_test.go +++ b/json_test.go @@ -2,9 +2,10 @@ package json import ( "encoding/json" + "fmt" "testing" - "github.com/yuin/gopher-lua" + lua "github.com/yuin/gopher-lua" ) func TestSimple(t *testing.T) { @@ -21,9 +22,6 @@ func TestSimple(t *testing.T) { assert(json.encode({}) == "[]") assert(json.encode({1, 2, 3}) == "[1,2,3]") - local _, err = json.encode({1, 2, [10] = 3}) - assert(string.find(err, "sparse array")) - local _, err = json.encode({1, 2, 3, name = "Tim"}) assert(string.find(err, "mixed or invalid key types")) @@ -62,6 +60,8 @@ func TestSimple(t *testing.T) { a[i] = i end assert(json.encode(a) == "[1,2,3,4,5]") + + assert(json.encode(json) == nil) ` s := lua.NewState() defer s.Close() @@ -97,3 +97,59 @@ func TestDecodeValue_jsonNumber(t *testing.T) { t.Fatalf("expecting LString, got %T", v) } } + +func TestEncode_SparseArray(t *testing.T) { + tests := []struct { + table string + expected string + }{ + { + table: `{ + 1, + 2, + [10] = 3 + }`, + expected: `[1,2,"[10] = 3"]`, + }, + { + table: `{ + nested = { + [37] = "index 37" + } + }`, + expected: `{"nested":["[37] = index 37"]}`, + }, + { + table: `{ + nested = { + "index 1", + [37] = "index 37" + } + }`, + expected: `{"nested":["index 1","[37] = index 37"]}`, + }, + { + table: `{ + nested = { + "index 1", + [37] = "index 37" + } + }`, + expected: `{"nested":["index 1","[37] = index 37"]}`, + }, + } + + for _, test := range tests { + s := lua.NewState() + defer s.Close() + Preload(s) + + luaScript := fmt.Sprintf(` + local json = require("json") + local t = %s + assert(json.encode(t) == '%s')`, test.table, test.expected) + if err := s.DoString(luaScript); err != nil { + t.Error(err) + } + } +}