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 8d81fc39 fix(arrow/array): handle exponent notation for unmarshal int 
(#662)
8d81fc39 is described below

commit 8d81fc39254b7a51daf1fe1a272c24169a059878
Author: Matt Topol <[email protected]>
AuthorDate: Wed Feb 11 17:19:53 2026 -0500

    fix(arrow/array): handle exponent notation for unmarshal int (#662)
    
    ### Rationale for this change
    fixes #474
    
    ### What changes are included in this PR?
    Modify unmarshal methods to try parseint/parseuint first, and to
    fallback to ParseFloat to handle exponential notation.
    
    ### Are these changes tested?
    A test is added to confirm
    
    ### Are there any user-facing changes?
    Just the bug fix
---
 arrow/array/json_reader_test.go        |  72 +++++++
 arrow/array/numericbuilder.gen.go      | 364 +++++++++++++++++++++++++++++++++
 arrow/array/numericbuilder.gen.go.tmpl | 103 ++++++++++
 3 files changed, 539 insertions(+)

diff --git a/arrow/array/json_reader_test.go b/arrow/array/json_reader_test.go
index 854c8eac..d309b0c3 100644
--- a/arrow/array/json_reader_test.go
+++ b/arrow/array/json_reader_test.go
@@ -143,6 +143,78 @@ func TestUnmarshalJSON(t *testing.T) {
        assert.NotNil(t, record)
 }
 
+func TestJSONReaderExponentialNotation(t *testing.T) {
+       tests := []struct {
+               name     string
+               dataType arrow.DataType
+               input    string
+               expected interface{}
+       }{
+               {
+                       name:     "int64 exponential notation",
+                       dataType: arrow.PrimitiveTypes.Int64,
+                       input:    `{"value":"6.6999677E+8"}`,
+                       expected: int64(669996770),
+               },
+               {
+                       name:     "uint64 exponential notation",
+                       dataType: arrow.PrimitiveTypes.Uint64,
+                       input:    `{"value":"6.6999677E+8"}`,
+                       expected: uint64(669996770),
+               },
+               {
+                       name:     "int64 lowercase exponential",
+                       dataType: arrow.PrimitiveTypes.Int64,
+                       input:    `{"value":"1.5e+3"}`,
+                       expected: int64(1500),
+               },
+               {
+                       name:     "uint64 negative exponent",
+                       dataType: arrow.PrimitiveTypes.Uint64,
+                       input:    `{"value":"1.5e+3"}`,
+                       expected: uint64(1500),
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       schema := arrow.NewSchema([]arrow.Field{
+                               {Name: "value", Type: tt.dataType, Nullable: 
true},
+                       }, nil)
+
+                       mem := 
memory.NewCheckedAllocator(memory.NewGoAllocator())
+                       defer mem.AssertSize(t, 0)
+
+                       recordBuilder := array.NewRecordBuilder(mem, schema)
+                       defer recordBuilder.Release()
+
+                       err := recordBuilder.UnmarshalJSON([]byte(tt.input))
+                       if !assert.NoError(t, err, "should parse exponential 
notation") {
+                               return
+                       }
+
+                       record := recordBuilder.NewRecordBatch()
+                       defer record.Release()
+
+                       if !assert.Equal(t, int64(1), record.NumRows()) {
+                               return
+                       }
+                       col := record.Column(0)
+
+                       switch v := tt.expected.(type) {
+                       case int64:
+                               intCol, ok := col.(*array.Int64)
+                               assert.True(t, ok)
+                               assert.Equal(t, v, intCol.Value(0))
+                       case uint64:
+                               uintCol, ok := col.(*array.Uint64)
+                               assert.True(t, ok)
+                               assert.Equal(t, v, uintCol.Value(0))
+                       }
+               })
+       }
+}
+
 func generateJSONData(n int) []byte {
        records := make([]map[string]any, n)
        for i := range n {
diff --git a/arrow/array/numericbuilder.gen.go 
b/arrow/array/numericbuilder.gen.go
index be87fbf4..aa2f628d 100644
--- a/arrow/array/numericbuilder.gen.go
+++ b/arrow/array/numericbuilder.gen.go
@@ -218,7 +218,29 @@ func (b *Int64Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v, 10, 8*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(int64(fval)) || fval < 
-9223372036854775808.0 || fval >= 9223372036854775808.0 {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -230,7 +252,29 @@ func (b *Int64Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(int64(v))
        case json.Number:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v.String(), 10, 8*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(int64(fval)) || fval < 
-9223372036854775808.0 || fval >= 9223372036854775808.0 {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -459,7 +503,29 @@ func (b *Uint64Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v, 10, 8*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint64(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -471,7 +537,29 @@ func (b *Uint64Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(uint64(v))
        case json.Number:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v.String(), 10, 8*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint64(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint64(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -941,7 +1029,31 @@ func (b *Int32Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v, 10, 4*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (4*8 - 1))
+                       maxVal := float64(int64(1) << (4*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -953,7 +1065,31 @@ func (b *Int32Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(int32(v))
        case json.Number:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v.String(), 10, 4*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (4*8 - 1))
+                       maxVal := float64(int64(1) << (4*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -1182,7 +1318,29 @@ func (b *Uint32Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v, 10, 4*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint32(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -1194,7 +1352,29 @@ func (b *Uint32Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(uint32(v))
        case json.Number:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v.String(), 10, 4*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint32(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint32(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -1664,7 +1844,31 @@ func (b *Int16Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v, 10, 2*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (2*8 - 1))
+                       maxVal := float64(int64(1) << (2*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -1676,7 +1880,31 @@ func (b *Int16Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(int16(v))
        case json.Number:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v.String(), 10, 2*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (2*8 - 1))
+                       maxVal := float64(int64(1) << (2*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -1905,7 +2133,29 @@ func (b *Uint16Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v, 10, 2*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint16(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -1917,7 +2167,29 @@ func (b *Uint16Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(uint16(v))
        case json.Number:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v.String(), 10, 2*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint16(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint16(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -2146,7 +2418,31 @@ func (b *Int8Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v, 10, 1*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (1*8 - 1))
+                       maxVal := float64(int64(1) << (1*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(int8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -2158,7 +2454,31 @@ func (b *Int8Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(int8(v))
        case json.Number:
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v.String(), 10, 1*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       minVal := float64(int64(-1) << (1*8 - 1))
+                       maxVal := float64(int64(1) << (1*8 - 1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(int8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
@@ -2387,7 +2707,29 @@ func (b *Uint8Builder) UnmarshalOne(dec *json.Decoder) 
error {
                b.AppendNull()
 
        case string:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v, 10, 1*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint8(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v,
+                                       Type:   reflect.TypeOf(uint8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v,
@@ -2399,7 +2741,29 @@ func (b *Uint8Builder) UnmarshalOne(dec *json.Decoder) 
error {
        case float64:
                b.Append(uint8(v))
        case json.Number:
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v.String(), 10, 1*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^uint8(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value:  v.String(),
+                                       Type:   reflect.TypeOf(uint8(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
                if err != nil {
                        return &json.UnmarshalTypeError{
                                Value:  v.String(),
diff --git a/arrow/array/numericbuilder.gen.go.tmpl 
b/arrow/array/numericbuilder.gen.go.tmpl
index 518b3d4c..5569b2eb 100644
--- a/arrow/array/numericbuilder.gen.go.tmpl
+++ b/arrow/array/numericbuilder.gen.go.tmpl
@@ -17,6 +17,9 @@
 package array
 
 import (
+       "reflect"
+       "strconv"
+
        "github.com/apache/arrow-go/v18/arrow"
        "github.com/apache/arrow-go/v18/arrow/bitutil"
        "github.com/apache/arrow-go/v18/arrow/internal/debug"
@@ -378,9 +381,59 @@ func (b *{{.Name}}Builder) UnmarshalOne(dec *json.Decoder) 
error {
 {{if or (eq .Name "Float32") (eq .Name "Float64") -}}
                f, err := strconv.ParseFloat(v, {{.Size}}*8)
 {{else if eq (printf "%.1s" .Name) "U" -}}
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v, 10, {{.Size}}*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value: v,
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^{{.name}}(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value: v,
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
 {{else -}}
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v, 10, {{.Size}}*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v, 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value: v,
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       {{if eq .Size "8" -}}
+                       if fval != float64(int64(fval)) || fval < 
-9223372036854775808.0 || fval >= 9223372036854775808.0 {
+                       {{else -}}
+                       minVal := float64(int64(-1) << ({{.Size}}*8-1))
+                       maxVal := float64(int64(1) << ({{.Size}}*8-1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                       {{end -}}
+                               return &json.UnmarshalTypeError{
+                                       Value: v,
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
 {{end -}}
                if err != nil {
                        return &json.UnmarshalTypeError{
@@ -396,9 +449,59 @@ func (b *{{.Name}}Builder) UnmarshalOne(dec *json.Decoder) 
error {
 {{if or (eq .Name "Float32") (eq .Name "Float64") -}}
                f, err := strconv.ParseFloat(v.String(), {{.Size}}*8)
 {{else if eq (printf "%.1s" .Name) "U" -}}
+               // Try ParseUint first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseUint(v.String(), 10, {{.Size}}*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value: v.String(),
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       if fval != float64(uint64(fval)) || fval < 0 || fval > 
float64(^{{.name}}(0)) {
+                               return &json.UnmarshalTypeError{
+                                       Value: v.String(),
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = uint64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
 {{else -}}
+               // Try ParseInt first for direct integer strings, fall back to 
ParseFloat for exponential notation
                f, err := strconv.ParseInt(v.String(), 10, {{.Size}}*8)
+               if err != nil {
+                       // Could be exponential notation - try parsing as float
+                       fval, ferr := strconv.ParseFloat(v.String(), 64)
+                       if ferr != nil {
+                               return &json.UnmarshalTypeError{
+                                       Value: v.String(),
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       // Check if it's a whole number and in valid range
+                       {{if eq .Size "8" -}}
+                       if fval != float64(int64(fval)) || fval < 
-9223372036854775808.0 || fval >= 9223372036854775808.0 {
+                       {{else -}}
+                       minVal := float64(int64(-1) << ({{.Size}}*8-1))
+                       maxVal := float64(int64(1) << ({{.Size}}*8-1))
+                       if fval != float64(int64(fval)) || fval < minVal || 
fval >= maxVal {
+                       {{end -}}
+                               return &json.UnmarshalTypeError{
+                                       Value: v.String(),
+                                       Type: reflect.TypeOf({{.name}}(0)),
+                                       Offset: dec.InputOffset(),
+                               }
+                       }
+                       f = int64(fval)
+                       err = nil // Clear error after successful float parsing
+               }
 {{end -}}
                if err != nil {
                        return &json.UnmarshalTypeError{

Reply via email to