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{