This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 51b21f83 fix(arrow/array): preserve rows for empty-schema JSON input
(#1117)
51b21f83 is described below
commit 51b21f83ccb0f84df839bc9b2ca10aac7a2d56cd
Author: Minh Vu <[email protected]>
AuthorDate: Fri Aug 7 21:18:55 2026 +0200
fix(arrow/array): preserve rows for empty-schema JSON input (#1117)
### Rationale for this change
JSONReader currently derives the row count from field builder lengths.
With an empty schema there are no field builders, so valid JSON objects
are reported as zero-row batches.
### What changes are included in this PR?
Track decoded rows independently so single-record and whole-input reads
preserve rows even when the schema has no fields.
### Are these changes tested?
- `go test ./arrow/array`
### Are there any user-facing changes?
No API changes. This corrects the reported behavior while preserving the
existing ownership and compatibility contracts.
---
arrow/array/json_reader.go | 22 ++++++++++++++++++----
arrow/array/json_reader_test.go | 28 ++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/arrow/array/json_reader.go b/arrow/array/json_reader.go
index 86f3383f..52938af0 100644
--- a/arrow/array/json_reader.go
+++ b/arrow/array/json_reader.go
@@ -184,11 +184,17 @@ func (r *JSONReader) readNext() bool {
}
func (r *JSONReader) nextall() bool {
+ n := 0
for r.readNext() {
+ n++
}
- r.cur = r.bldr.NewRecordBatch()
- return r.cur.NumRows() > 0
+ if r.schema.NumFields() == 0 {
+ r.cur = NewRecordBatch(r.schema, nil, int64(n))
+ } else {
+ r.cur = r.bldr.NewRecordBatch()
+ }
+ return n > 0
}
func (r *JSONReader) next1() bool {
@@ -196,7 +202,11 @@ func (r *JSONReader) next1() bool {
return false
}
- r.cur = r.bldr.NewRecordBatch()
+ if r.schema.NumFields() == 0 {
+ r.cur = NewRecordBatch(r.schema, nil, 1)
+ } else {
+ r.cur = r.bldr.NewRecordBatch()
+ }
return true
}
@@ -210,7 +220,11 @@ func (r *JSONReader) nextn() bool {
}
if n > 0 {
- r.cur = r.bldr.NewRecordBatch()
+ if r.schema.NumFields() == 0 {
+ r.cur = NewRecordBatch(r.schema, nil, int64(n))
+ } else {
+ r.cur = r.bldr.NewRecordBatch()
+ }
}
return n > 0
}
diff --git a/arrow/array/json_reader_test.go b/arrow/array/json_reader_test.go
index 3d0def65..4254347e 100644
--- a/arrow/array/json_reader_test.go
+++ b/arrow/array/json_reader_test.go
@@ -95,6 +95,34 @@ func TestJSONReaderAll(t *testing.T) {
assert.False(t, rdr.Next())
}
+func TestJSONReaderPreservesRowsForEmptySchema(t *testing.T) {
+ schema := arrow.NewSchema(nil, nil)
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ t.Run("one row per batch", func(t *testing.T) {
+ rdr := array.NewJSONReader(strings.NewReader("{} {}"), schema,
array.WithAllocator(mem))
+ defer rdr.Release()
+
+ assert.True(t, rdr.Next())
+ assert.EqualValues(t, 1, rdr.RecordBatch().NumRows())
+ assert.True(t, rdr.Next())
+ assert.EqualValues(t, 1, rdr.RecordBatch().NumRows())
+ assert.False(t, rdr.Next())
+ assert.NoError(t, rdr.Err())
+ })
+
+ t.Run("all rows in one batch", func(t *testing.T) {
+ rdr := array.NewJSONReader(strings.NewReader("{} {}"), schema,
array.WithAllocator(mem), array.WithChunk(-1))
+ defer rdr.Release()
+
+ assert.True(t, rdr.Next())
+ assert.EqualValues(t, 2, rdr.RecordBatch().NumRows())
+ assert.False(t, rdr.Next())
+ assert.NoError(t, rdr.Err())
+ })
+}
+
func TestJSONReaderChunked(t *testing.T) {
schema := arrow.NewSchema([]arrow.Field{
{Name: "region", Type: arrow.BinaryTypes.String, Nullable:
true},