Skip to content

Commit

Permalink
upgrade ints and floats in arrays with mixed sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
grische committed Jul 31, 2024
1 parent c162664 commit b425394
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
49 changes: 49 additions & 0 deletions json-to-go.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
continue
}

// if variable was first detected as int (7) and a second time as float64 (3.14)
// then we want to select float64, not int. Similar for int64 and float64.
if(areSameType(currentValue, 1))
allFields[keyname].value = findBestValueForNumberType(existingValue, currentValue);

if (areObjects(existingValue, currentValue)) {
const comparisonResult = compareObjectKeys(
Object.keys(currentValue),
Expand Down Expand Up @@ -389,6 +394,50 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
}
}

// change the value to expand ints and floats to their larger equivalent
function findBestValueForNumberType(existingValue, newValue) {
if (!areSameType(newValue, 1)) {
console.error(`Error: currentValue ${newValue} is not a number`)
return null // falls back to goType "any"
}

const newGoType = goType(newValue)
const existingGoType = goType(existingValue)

if (newGoType === existingGoType)
return existingValue

// always upgrade float64
if (newGoType === "float64")
return newValue
if (existingGoType === "float64")
return existingValue

// it's too complex to distinguish int types and float32, so we force-upgrade to float64
// if anyone has a better suggestion, PRs are welcome!
if (newGoType.includes("float") && existingGoType.includes("int"))
return Number.MAX_VALUE
if (newGoType.includes("int") && existingGoType.includes("float"))
return Number.MAX_VALUE

if (newGoType.includes("int") && existingGoType.includes("int")) {
const existingValueAbs = Math.abs(existingValue);
const newValueAbs = Math.abs(newValue);

// if the sum is overflowing, it's safe to assume numbers are very large. So we force int64.
if (!isFinite(existingValueAbs + newValueAbs))
return Number.MAX_SAFE_INTEGER

// it's too complex to distinguish int8, int16, int32 and int64, so we just use the sum as best-guess
return existingValueAbs + newValueAbs;
}

// There should be other cases
console.error(`Error: something went wrong with findBestValueForNumberType() using the values: '${newValue}' and '${existingValue}'`)
console.error(" Please report the problem to https://github.com/mholt/json-to-go/issues")
return null // falls back to goType "any"
}

// Given two types, returns the more specific of the two
function mostSpecificPossibleGoType(typ1, typ2)
{
Expand Down
1 change: 1 addition & 0 deletions json-to-go.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ function testFiles() {
const testCases = [
"duplicate-top-level-structs",
"double-nested-objects",
"array-with-mixed-float-int",
"array-with-nonmatching-types",
];

Expand Down
13 changes: 13 additions & 0 deletions tests/array-with-mixed-float-int.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type AutoGenerated struct {
AgeOfTheUniverse []AgeOfTheUniverse `json:"age of the universe"`
AgeOfTheEarth []AgeOfTheEarth `json:"age of the earth"`
Date string `json:"date"`
}
type AgeOfTheUniverse struct {
Name string `json:"name"`
Value float64 `json:"value"`
}
type AgeOfTheEarth struct {
Name string `json:"name"`
Value int64 `json:"value"`
}
31 changes: 31 additions & 0 deletions tests/array-with-mixed-float-int.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"age of the universe": [
{
"name": "in years",
"value": 1378700000
},
{
"name": "in seconds",
"value": 4.35075327952992e+17
},
{
"name": "in kapla",
"value": 0.31914351851
}
],
"age of the earth": [
{
"name": "in eons (roughly)",
"value": 4
},
{
"name": "in years",
"value": 4.543e9
},
{
"name": "in seconds",
"value": 1.6592953e+12
}
],
"date": "2024-07-25"
}

0 comments on commit b425394

Please sign in to comment.