Skip to content

bug: parsing big integers in JSON data loses precision #489

Closed

Description

@lance

Describe the Bug
When parsing JSON data, if a JSON field value is a number, and that number is really big, JavaScript loses precision. For example, the Twitter API exposes the Tweet ID. This is a large number that exceeds the integer space of Number. You can see this by simply assigning a large number to a simple variable (it's not actually JSON that is the problem, it's JavaScript itself).

> let id = 1524831183200260097
undefined
> id
1524831183200260000

Steps to Reproduce

❯ npm install cloudevents
❯ cat > index.js
const { CloudEvent } = require('cloudevents')

let e = new CloudEvent({ source: 'example', type: 'example', data: 1524831183200260097 })
console.log(e.data)
^D
❯ node index.js
1524831183200260000

Expected Behavior
I expect the data to not lose precision.

Additional context
This can be resolved by using json-bigint

> let JSON = require('json-bigint')({useNativeBigInt: true})
> let j = JSON.parse('{ "key": 993143214321423154315154321 }')
> j.key
993143214321423154315154321

Activity

  1. cardil commented on May 13, 2022

    @cardil

    I think your Steps to Reproduce are a little misleading. You type there in verbatim a long number. JavaScript engine, parse a file, and use IEEE 754 Standard to parse a Number. You could avoid that by using BigInt notation:

    let e = new CloudEvent({ source: 'example', type: 'example', data: 1524831183200260097n })

    The problem exists, though. It lies in parsers implemented in this library. Here's simple jest for HTTP:

    const { HTTP } = require('cloudevents')
    
    test('Parse big numbers from HTTP', () => {
      let ce = HTTP.toEvent({
        headers: { 'content-type': 'application/cloudevents+json' },
        body: `{"id": 1524831183200260097}`
      })
      expect(ce.id).toBe(1524831183200260097n);
    })

    This test fails:

      ● Parse big numbers from HTTP
    
        expect(received).toBe(expected) // Object.is equality
    
        Expected: 1524831183200260097n
        Received: 1524831183200260000
    
           6 |     body: `{"id": 1524831183200260097}`
           7 |   })
        >  8 |   expect(ce.id).toBe(1524831183200260097n)
             |                 ^
           9 | })
          10 |
          11 |
    
          at Object.toBe (bigint.test.js:8:17)
    
  2. github-actions commented on Jun 13, 2022

    @github-actions
    Contributor

    This issue is stale because it has been open 30 days with no activity.

  3. lance commented on Jun 14, 2022

    @lance
    MemberAuthor

    @cardil you are correct to point out the error in my example. But your example would not produce a valid CE even if we could handle big integers, because the required type for the id field is String. https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#id

    I think this is still a problem, but if something is sending a big int for the id that's not going to fly.

  4. github-actions commented on Jul 15, 2022

    @github-actions
    Contributor

    This issue is stale because it has been open 30 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions