jsonnode.jslong-integerfetch-apitruncated

fetch() response truncating big numbers


I have fetch() setup to retrieve historical webinar details from GotoWebinar using their API. It returns a JSON body with this structure, an array of objects:

[{ "webinarKey":5653814518315977731, "webinarID":"562189251", "subject":"Sample Webinar", "organizerKey":100000000000331530 }, { "webinarKey":9999814518315977731, "webinarID":"999989251", "subject":"Sample Webinar", "organizerKey":999900000000331530 }]

My code is being implented in a Zapier action(node.js) and the important bit looks like this:

//Handle errors from fetch call
function handleFetchStatus(response){
    console.log('Fetch Response Status: ' + response.status);

    switch(response.status){
        case 200: //Request executed properly
            break;

        default:
            throw Error(response.status + ':' + JSON.stringify(response));
    }

    return response.json();

}

function handleFetchBody(oResponse){
    if (oResponse) {
        console.log('handleFetchBody: ' + JSON.stringify(oResponse));
    }

    callback(null, oResponse);
}


//Send POST request.
fetch(getFetchURL(), getFetchOptions())
    .then(handleFetchStatus)
    .then(handleFetchBody)
    .catch(function(error) {
        callback(error);
    });

The problem I've got is that the 'webinarKey', a long number, is being truncated from "5653814518315977731" to "5653814518315978000". I believe it's the json() function that isn't handling large numbers.

How can I stop this?

I believe I need to turn the webinarKey into a string before I use json(), but I'm not sure how to access all elements of the object. Is that even possible in a fetch response.


Solution

  • It has to do with the number of digits of precision in JavaScript. In JavaScript, all numbers are stored as floating-point, which is like scientific notation in base 2 instead of base 10. There is a fixed number of bits (53 in this case) available to represent a in a * (2 ** b). If you look at Number.MAX_SAFE_INTEGER, the greatest integer that can be represented with 53 bits of precision, you will see that it has 16 base-10 digits. Your number has 19. If you just type the number into a JavaScript console, you will see that it prints out the rounded version (with 16 digits of precision). If you need to be storing such large numbers, it is usually best to store them as strings.