3

I'm trying to make a POST (add) request that returns the ID of the added item. The ID is an 18 character string. Everything works fine as long as the string is 16 characters or less. When it is 18 characters long the last two characters are always corrupted since they default to zero.

I'm using Vuejs as my frontend and a SpringBoot as my backend. I'm aware of the javascript limitation of 53 bits of precision for a Long which is why I'm using String as my Type for this ID. I would expect this to happen if I was trying to return a 18 digit number but not an 18 character string. It appears that although I return a type STRING, Axios is automatically converting it to a LONG which causes it to get corrupted. How do I tell Axios not to do this? ## Heading ##Thanks.

========= Backend restcontroller endpoint =============

@PostMapping("/persons")
public ResponseEntity<String> addPerson(@Valid @RequestBody Person person) {
    String newPersonId = personService.addPerson(person);
    return new ResponseEntity<>(newPersonId, HttpStatus.OK);
}

==============Frontend Axios POST call ===================

axios
    .post("http://localhost:xxxx/persons", newPerson)
    .then(response => {
      console.log("Response from post is: " + response.data);
      console.log(response);
      newPerson.id = response.data;
    })
    .catch(error => console.log(error));

========== Console OUTPUT: =============

The following line is the console.log print statement from my frontend Post call. This shows that I received the ID and last two digits as zero.

Response from post is: 622056030329638900


Notice that response.data (line3 below) ends in 900 and is not surrounded by quotes. If you read further down - response.request.response (line 10 & 11) ends in 912 which is the correct response. I think I know why they dont match (Axios converts it to a Long and it gets corrupted by the 53 bit precision limitation) but I dont understand why Axios is converting the String to a Long in the first place.


  1. {data: 622056030329638900, status: 200, statusText: "", headers: {…}, config: {…}, …}
  2. config: {url: "http://localhost:xxxx/persons", method: "post", data: "{"firstName":"daffy","middleName":"woddle","lastName":"duck","homeEmail":"daffy@gmail.com"}", headers: {…}, transformRequest: Array(1), …}
  3. data: 622056030329638900
  4. headers: {content-length: "18", content-type: "application/json;charset=UTF-8"}
  5. request: XMLHttpRequest
  6. onabort: ƒ handleAbort()
  7. onerror: ƒ handleError()
  8. onload: null
  9. onloadend: null
  10. onloadstart: null
  11. onprogress: null
  12. onreadystatechange: ƒ handleLoad()
  13. ontimeout: ƒ handleTimeout()
  14. readyState: 4
  15. response: "622056030329638912"
  16. responseText: "622056030329638912"
  17. responseType: ""
  18. responseURL: "http://localhost:xxxx/persons"
  19. responseXML: null
  20. status: 200
  21. statusText: ""
  22. timeout: 0

Expect Result: All 18 characters sent match the ones received. Actual Result: The first 16 characters match, the last two are zero.

o-tinoco
  • 59
  • 9
fivemikes
  • 33
  • 1
  • 4

3 Answers3

2

The problem ultimately comes down to the fact, that a string like "12334" isnt a valid JSON string, (but a valid JSON number). See this question

<script>
    // 1233
    alert(JSON.parse("1234")); // treated as a number

    // SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
    alert(JSON.parse("ABC"));
</script>

Axios transforms the response by default in this way (it parses json):

  transformResponse: [function transformResponse(data) {
    /*eslint no-param-reassign:0*/
    if (typeof data === 'string') {
      try {
        data = JSON.parse(data);
      } catch (e) { /* Ignore */ }
    }
    return data;
  }],

So if you have following options:

One: Return a valid Json String like this: "\"622056030329638912\"" (JSON ENCODE on Server Side)

    alert(JSON.parse("\"622056030329638912\""));

Two: Disable transformation at axios:

    axios
        .post("http://localhost:xxxx/persons", newPerson, {
            transformResponse: function(response) {
                // do not transform response at all... 
                return response;
            }
         })
        .then(response => {
            console.log("Response from post is: " + response.data);
            console.log(response);
            newPerson.id = response.data;
        })
        .catch(error => console.log(error));
shock_gone_wild
  • 6,700
  • 4
  • 28
  • 52
1

That number (622056030329638912) is too big for JavaScript. Take a look at Number.MAX_SAFE_INTEGER, the value is 9007199254740991. Anything greater than the max safe integer is not safe to use as a number in your browser.

Treat it as a string, if you can. Have your API return a string value if you must use response.data. Otherwise, using responseText should be fine.

The MAX_SAFE_INTEGER constant has a value of 9007199254740991 (9,007,199,254,740,991 or ~9 quadrillion). The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(2^53 - 1) and 2^53 - 1.

Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect. See Number.isSafeInteger() for more information.

Here's a demonstration:

console.log(Number.MAX_SAFE_INTEGER);
console.log(622056030329638922);
Community
  • 1
  • 1
Tom Faltesek
  • 2,768
  • 1
  • 19
  • 30
0

try using object to return in your back-end:

{value: "622056030329638900"}

this worked for me!

Darlan Dieterich
  • 2,369
  • 1
  • 27
  • 37
  • Yes I wasnt having this problem with my objects either - now I understand why – fivemikes Sep 13 '19 at 16:50
  • @fivemikes It is not good practice to work with response handling. Imagine your application is always looking at the header for a data type, this will affect the performance. You should be aware of what you are expecting, so return an object as good practice! – Darlan Dieterich Sep 13 '19 at 17:52