javascriptpythonjsonnumbers

Why is my individual Tweet ID number changing last few digits to "0" when received in JavaScript?


I'm using Tweepy python library to access the Twitter API to retrieve cryptocurrency tweets. My application uses a Django backend and a ReactJs frontend. While my web-app will show the retrieved tweet itself, I intend to also have a clickable link available, to re-route to the original on Twitter.

My Django Rest Framework API is retrieving the correct Tweet ID number in full when returning a JSON. However, when I'm retrieving from the Rest Framework API to my Frontend, the last few digits of the Tweet ID number is changed to "0". I wonder if this is a default protection measure that Twitter uses?

Django Rest API:

…
"bitcoin_tweet_user": "TheStarPhoenix",
"bitcoin_tweet": "Teslas can now be bought for bitcoin, Elon Musk says […]",
"bitcoin_tweet_link": 1375092596339585038,
…

Front-End of Website:

enter image description here

App.js:

<div className="center-column-tweet">
    <div className="item-row-tweets">
        <div className="left">
            <span>
                <b>@{tasks.bitcoin_tweet_user}</b><br/><br/>
                "{tasks.bitcoin_tweet}"<br/>
                <b>Link:</b> https://twitter.com/twitter/statuses/{tasks.bitcoin_tweet_link}
            </span>
         </div>
     </div>
</div>

Solution

  • You have become the victim of floating-point rounding.

    Number values in JSON are represented roughly as a sequence of decimal digits, optionally followed by a decimal point and then more digits0, and in principle, the digit sequences can be arbitrarily long. However, this does not mean that every JSON implementation will actually support arbitrarily-large numbers and preserve their value exactly: Python’s json module does (at least for integers), since the language supports arbitrarily-large integers as a built-in feature, but most other implementations do not. In practice, JSON numbers are often parsed into IEEE 754 double-precision floating-point values; when a value is encountered that cannot be represented exactly by that number format, the number is usually rounded to the nearest representable value. This is what happens in JavaScript: the number 1375092596339585038 is too large to be represented exactly by the JavaScript number type, and so, when it is parsed on the JavaScript side, it is rounded to the nearest representable value, which is then printed as 1375092596339585000.

    (That the original JSON specification doesn’t define any range of numbers that every implementation must support, and doesn’t define what should happen when a value cannot be parsed exactly, is one of the many flaws in JSON.)

    You should change the API so that the tweet ID is returned as string instead of a number. Given that a tweet ID is not a quantity anyway (there is no reason to ever perform arithmetic on it, for example), you are not going to lose much by doing that.

    Alternatively, once the “JSON parse with source” proposal lands in browsers, you might want to use that – although availability is still limited, and in this case there seems to be no particular benefit to it.


    0 I’m not mentioning the exponential notation for simplicity.