Skip to content

Commit 342ae50

Browse files
committed
add support for all basic golang number types
this also fixes a bug where an int64 was detected for a number larger than the largest int64 number
1 parent 1e827f8 commit 342ae50

6 files changed

+79
-27
lines changed

json-to-go.js

+26-8
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,17 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
349349
// Determines the most appropriate Go type
350350
function goType(val)
351351
{
352+
Number.prototype.numberOfDecimals = function () {
353+
if(isNaN(this)) return NaN
354+
if(!isFinite(this)) return Infinity
355+
// example: 1 || 1e-1 || 4.361170766e+20
356+
// try to split by "e" and "."
357+
let exponentialString = this.toExponential().toString()
358+
exponentialString = exponentialString.split("e")[0] || exponentialString
359+
exponentialString = exponentialString.split(".")[1] || exponentialString
360+
return exponentialString.length || 0;
361+
}
362+
352363
if (val === null)
353364
return "any";
354365

@@ -360,15 +371,22 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
360371
else
361372
return "string";
362373
case "number":
363-
if (val % 1 === 0)
364-
{
365-
if (val > -2147483648 && val < 2147483647)
366-
return "int";
367-
else
368-
return "int64";
369-
}
370-
else
374+
// avoid type "int", as its size is platform dependent
375+
if (val % 1 === 0 && val >= -128 && val <= 127)
376+
return "int8"
377+
if (val % 1 === 0 && val >= -32768 && val <= 32767)
378+
return "int16"
379+
if (val % 1 === 0 && val >= -2147483648 && val <= 2147483647)
380+
return "int32"
381+
if (val % 1 === 0 && val >= -9223372036854775808 && val <= 9223372036854775807)
382+
return "int64"
383+
if (val.numberOfDecimals() <= 7 && val > -3.4e+38 && val < 3.4e+38)
384+
return "float32"
385+
if (val.numberOfDecimals() <= 15 && val > -1.7e+308 && val < +1.7e+308)
371386
return "float64";
387+
388+
console.error(`Warning: can't find matching Golang number type for '${val}'. Falling back to "any".`)
389+
return "any";
372390
case "boolean":
373391
return "bool";
374392
case "object":

json-to-go.test.js

+15-14
Original file line numberDiff line numberDiff line change
@@ -76,51 +76,51 @@ function test(includeExampleData) {
7676
{
7777
input: '{"age": 46}',
7878
expected:
79-
'type AutoGenerated struct {\n\tAge int `json:"age"`\n}\n',
79+
'type AutoGenerated struct {\n\tAge int8 `json:"age"`\n}\n',
8080
expectedWithExample:
81-
'type AutoGenerated struct {\n\tAge int `json:"age" example:"46"`\n}\n',
81+
'type AutoGenerated struct {\n\tAge int8 `json:"age" example:"46"`\n}\n',
8282
},
8383
{
8484
input: '{"negativeFloat": -1.00}',
8585
expected:
86-
'type AutoGenerated struct {\n\tNegativeFloat float64 `json:"negativeFloat"`\n}\n',
86+
'type AutoGenerated struct {\n\tNegativeFloat float32 `json:"negativeFloat"`\n}\n',
8787
expectedWithExample:
88-
'type AutoGenerated struct {\n\tNegativeFloat float64 `json:"negativeFloat" example:"-1.1"`\n}\n',
88+
'type AutoGenerated struct {\n\tNegativeFloat float32 `json:"negativeFloat" example:"-1.1"`\n}\n',
8989
},
9090
{
9191
input: '{"zeroFloat": 0.00}',
9292
expected:
93-
'type AutoGenerated struct {\n\tZeroFloat float64 `json:"zeroFloat"`\n}\n',
93+
'type AutoGenerated struct {\n\tZeroFloat float32 `json:"zeroFloat"`\n}\n',
9494
expectedWithExample:
95-
'type AutoGenerated struct {\n\tZeroFloat float64 `json:"zeroFloat" example:"0.1"`\n}\n',
95+
'type AutoGenerated struct {\n\tZeroFloat float32 `json:"zeroFloat" example:"0.1"`\n}\n',
9696
},
9797
{
9898
input: '{"positiveFloat": 1.00}',
9999
expected:
100-
'type AutoGenerated struct {\n\tPositiveFloat float64 `json:"positiveFloat"`\n}\n',
100+
'type AutoGenerated struct {\n\tPositiveFloat float32 `json:"positiveFloat"`\n}\n',
101101
expectedWithExample:
102-
'type AutoGenerated struct {\n\tPositiveFloat float64 `json:"positiveFloat" example:"1.1"`\n}\n',
102+
'type AutoGenerated struct {\n\tPositiveFloat float32 `json:"positiveFloat" example:"1.1"`\n}\n',
103103
},
104104
{
105105
input: '{"negativeFloats": [-1.00, -2.00, -3.00]}',
106106
expected:
107-
'type AutoGenerated struct {\n\tNegativeFloats []float64 `json:"negativeFloats"`\n}\n',
107+
'type AutoGenerated struct {\n\tNegativeFloats []float32 `json:"negativeFloats"`\n}\n',
108108
expectedWithExample:
109-
'type AutoGenerated struct {\n\tNegativeFloats []float64 `json:"negativeFloats"`\n}\n',
109+
'type AutoGenerated struct {\n\tNegativeFloats []float32 `json:"negativeFloats"`\n}\n',
110110
},
111111
{
112112
input: '{"zeroFloats": [0.00, 0.00, 0.00]}',
113113
expected:
114-
'type AutoGenerated struct {\n\tZeroFloats []float64 `json:"zeroFloats"`\n}\n',
114+
'type AutoGenerated struct {\n\tZeroFloats []float32 `json:"zeroFloats"`\n}\n',
115115
expectedWithExample:
116-
'type AutoGenerated struct {\n\tZeroFloats []float64 `json:"zeroFloats"`\n}\n',
116+
'type AutoGenerated struct {\n\tZeroFloats []float32 `json:"zeroFloats"`\n}\n',
117117
},
118118
{
119119
input: '{"positiveFloats": [1.00, 2.00, 3.00]}',
120120
expected:
121-
'type AutoGenerated struct {\n\tPositiveFloats []float64 `json:"positiveFloats"`\n}\n',
121+
'type AutoGenerated struct {\n\tPositiveFloats []float32 `json:"positiveFloats"`\n}\n',
122122
expectedWithExample:
123-
'type AutoGenerated struct {\n\tPositiveFloats []float64 `json:"positiveFloats"`\n}\n',
123+
'type AutoGenerated struct {\n\tPositiveFloats []float32 `json:"positiveFloats"`\n}\n',
124124
},
125125
{
126126
input: '{"topLevel": { "secondLevel": "exampleDataHere"} }',
@@ -162,6 +162,7 @@ function testFiles() {
162162
const testCases = [
163163
"duplicate-top-level-structs",
164164
"double-nested-objects",
165+
"supported-number-types",
165166
];
166167

167168
for (const testCase of testCases) {

tests/double-nested-objects.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ type Type struct {
77
Long string `json:"long"`
88
}
99
type First struct {
10-
ID int `json:"id"`
10+
ID int8 `json:"id"`
1111
Type Type `json:"type"`
1212
}
1313
type SecondType struct {
1414
Long string `json:"long"`
1515
}
1616
type Second struct {
17-
ID int `json:"id"`
17+
ID int8 `json:"id"`
1818
SecondType SecondType `json:"type"`
1919
}

tests/duplicate-top-level-structs.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ type AutoGenerated struct {
55
}
66
type Identifier struct {
77
Type string `json:"type"`
8-
ID int `json:"id"`
8+
ID int16 `json:"id"`
99
}
1010
type Region struct {
1111
Identifier Identifier `json:"identifier"`
@@ -20,11 +20,11 @@ type Municipality struct {
2020
}
2121
type Postal struct {
2222
Type string `json:"type"`
23-
ID int `json:"id"`
23+
ID int8 `json:"id"`
2424
}
2525
type Road struct {
2626
Name string `json:"name"`
27-
ID int `json:"id"`
27+
ID int8 `json:"id"`
2828
}
2929
type BuildingIdentifier struct {
3030
Postal Postal `json:"postal"`

tests/supported-number-types.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type AutoGenerated struct {
2+
Basedonscience bool `json:"basedonscience"`
3+
SecondsPerYear float32 `json:"seconds per year"`
4+
AgeOfTheUniverse AgeOfTheUniverse `json:"age of the universe"`
5+
BasicallyInfinity any `json:"basically infinity"`
6+
Date string `json:"date"`
7+
}
8+
type AgeOfTheUniverse struct {
9+
InPlanckTime float64 `json:"in planck time"`
10+
InVeryPreciseMilliseconds float64 `json:"in very precise milliseconds"`
11+
InMilliseconds float32 `json:"in milliseconds"`
12+
InSeconds int64 `json:"in seconds"`
13+
InYears int64 `json:"in years"`
14+
InMillenia int32 `json:"in millenia"`
15+
InMegaannums int16 `json:"in megaannums"`
16+
InGalacticYears int8 `json:"in galactic years"`
17+
}

tests/supported-number-types.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"basedonscience": true,
3+
"seconds per year": 3.6524219e+2,
4+
"age of the universe": {
5+
"in planck time": 8.0718985e+60,
6+
"in very precise milliseconds": 4.35075327952992e+20,
7+
"in milliseconds": 4.3507532e+20,
8+
"in seconds": 4.35075327952992e+17,
9+
"in years": 13787000000,
10+
"in millenia": 13787000,
11+
"in megaannums": 13787,
12+
"in galactic years": 60
13+
},
14+
"basically infinity": 4.361170766e+400,
15+
"date": "2024-07-25"
16+
}

0 commit comments

Comments
 (0)