2

I am trying to set a large int value as an environment variable in Postman.

But Postman is rounding it off.

Is there any way I can handle this?

Tests:

var response = JSON.parse(responseBody); 
for(var i=0; i<=response.Offerings.length ; i++) {
    if(response.Offerings[i].DisplayName == 'Samsung Galaxy S9+') {
        console.log(response.Offerings[i].Id); 
    }
} 

API Response:

Response: { 
    "Offerings": [ 
        { 
            "Amount": 123,
            "CurrencyCode": "CAD",
            "DisplayName": "Samsung Galaxy S9+",
            "Id": 1910256760591000500,
            "Language": "en-CA",
            "LineOfBusinesses": [ 10048 ],
            "MarketingViews": [],
            "Name": "Samsung Galaxy S9+",
            "OfferType": 1,
        }
    ]
} 
n-verbitsky
  • 552
  • 2
  • 9
  • 20
Shriya Soni
  • 81
  • 1
  • 9
  • 1
    What does it mean? You you please put here you large int value and the "off rounded" value as well? – DieGraueEminenz May 29 '19 at 05:11
  • Store it as a string in the environment? – Sivcan Singh May 29 '19 at 05:28
  • Large Int Value is : 1910256760591000500 Round off value is : 1910256760591000600 The round off vale is not at all there in the API response. – Shriya Soni May 29 '19 at 06:15
  • I tried using toString() but not working. – Shriya Soni May 29 '19 at 06:20
  • can you please post your code here? – DieGraueEminenz May 29 '19 at 09:23
  • Possible duplicate of [Prevent JavaScript Number function from rounding big numbers](https://stackoverflow.com/questions/15529337/prevent-javascript-number-function-from-rounding-big-numbers) – barbsan May 29 '19 at 10:35
  • @DieGraueEminenz just paste 1910256760591000500 into your browser's console and see the output – barbsan May 29 '19 at 10:40
  • Tests: var response = JSON.parse(responseBody); for(var i=0; i<=response.Offerings.length ; i++) { if(response.Offerings[i].DisplayName == 'Samsung Galaxy S9+') { console.log(response.Offerings[i].Id); } } – Shriya Soni May 29 '19 at 13:59
  • API Response: Response: { "Offerings": [ { "Amount": 123, "CurrencyCode": "CAD", "DisplayName": "Samsung Galaxy S9+", "Id": 1910256760591000500, "Language": "en-CA", "LineOfBusinesses": [ 10048 ], "MarketingViews": [], "Name": "Samsung Galaxy S9+", "OfferType": 1, – Shriya Soni May 29 '19 at 14:01
  • This is mainly a problem with the API. If it's yours, you should change it so that it returns the id as a string because you're not using the id as an arithmetic number. The same problem will happen in the clients as well, depending on what languages they are using. – JJJ May 29 '19 at 14:09

4 Answers4

2

The problem

Yeah. So it isn't postman that is rounding off it is the base Javascript. Numbers in javascript are double precision floats. Bascially in Javascript the largest primitive number is 56 bits or as they call it MAX_SAFE_INTEGER - which is 9,007,199,254,740,991. Most languages are 64 bits(9,223,372,036,854,775,807). What happens in postman is the following:

  • You have a number that requires more than 56 bits.
  • Javascript wants to help you and converts it as good as it can
  • JSON.parse(responseBody) can't convert any number higher than 56 bits. So it does it best and you and up with something that looks like a rounded number.

Small Example would be this:

let x = 9223372036854775807
let y = BigInt(9223372036854775807)
let text = x.toString();
let z = parseInt(text, 10);
console.log(z) // 9223372036854776000

There are solutions to this in javascript. Namely a couple of libraries like "json-bigint". However including that in Postman is not exactly easy. Ironically Postman already makes use of BigInteger, but it does not work when the code you're executing is base javascript. But it is still the reason why @Plurimus solution should work.

What to do

Whenever you need a library in Postman there are ways to load it in using requests. Here users demonstrate how they load libraries mainly stored on cloudflare. And spoiler - json-bigint - is not there. It's an npmjs library which only makes it harder to add. One issue you are definitely going to run into is that Postman pre-requests are async. Which means your library might get loaded, but code that was supposed to use the library has already been executed. Luckily someone already found a hack for that.

A solution

In my solution I have a link to a library at my own personal github that I want to use. Always fork stuff like this. I then use postman get the code. And uses eval to override the JSON object. There is some preliminary code that shows the value before and after loading the library. The request is run in method called main which is an async method added to the pre-request in order to make sure that everything runs synchronously inside that function.

    console.log('hello');
    var libraryLink = 'https://gist.githubusercontent.com/kentkost/f2699eb1dd41e2eb6203f0d0c77a987e/raw/bffae74aa3827ea195c10cf83bce4d78017bdf2d/postman-bigint.js'

    let dummyJson = '{ "value" : 9223372036854775807, "v2": 123 }'
    let obj = JSON.parse(dummyJson)
    console.log(obj.value);
    console.log(JSON.stringify(obj));

    const _dummy = setInterval(() => {}, 300000);

    function sendRequest(req) {
        return new Promise((resolve, reject) => {
            pm.sendRequest(req, (err, res) => {
                if (err) {
                    return reject(err);
                }

                return resolve(res);
            })
        });
    }

    (async function main() {
        let result1 = await sendRequest(libraryLink);
        eval(result1.text());
        
        let newObj = JSON.parse(dummyJson);
        console.log(newObj.value);
        pm.environment.set("someVar", newObj.value);
        console.log(JSON.stringify(newObj));
        console.log('bye');
        clearInterval(_dummy)
    })();

Result of prerequest

Kent Kostelac
  • 2,257
  • 3
  • 29
  • 42
1

I've just had the same issue. Solved it by adding quotes to big numbers in response before parsing. Then you can get the variable and parse it as BigInt using additional libraries like they wrote

var responseBigIntsChangedToStrings = pm.response.text().replace(/([^"\w-])([-0-9.]{8,100})([^"\w-])/g, '$1\"$2\"$3');
var jsonResponse = [...responseBigIntsChangedToStrings.matchAll(/{.*}/g)];
var json = JSON.parse(jsonResponse);

You can try something like that:

var response = JSON.parse(responseBody.replace(/([^"\w-])([-0-9.]{8,100})([^"\w-])/g, '$1\"$2\"$3')); 
for(var i=0; i<=response.Offerings.length ; i++) 
{ 
       if(response.Offerings[i].DisplayName == 'Samsung Galaxy S9+') 
       {
           console.log(response.Offerings[i].Id); 
       } 
}
David Buck
  • 3,752
  • 35
  • 31
  • 35
Plurimus
  • 11
  • 1
0

You can manipulate the response by enclosing the int values with double quotes to treat them as strings and then do JSON.parse of stringified value, something like below:

let jsonStr = responseBody.toString();
const regex = "(\":)([0-9.]+)";
const matches = jsonStr.matchAll(regex);
for(const match of matches){
    jsonStr = jsonStr.replace(match[0], "\":\"" + match[2] + "\"");
}
var jsonData = JSON.parse(jsonStr);
console.log(jsonData.Offerings[i].Id); 

This way, you can overcome javascript limitation of default handling of bigint values in postman response.

Bhuvanesh Mani
  • 1,394
  • 14
  • 23
0

Same as above.. bit fine tuned..

var tResp = pm.response.text().replace(/([^"\w-])([-0-9.]{8,100})([^"\w-])/g, '$1\"$2\"$3');
var jsonData = JSON.parse(tResp);
var accountId = jsonData.accountkey.replace('"',''); 

console.log("accountId is "+accountId);
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 27 '23 at 00:25