【问题标题】:How to return 18 character string response from an Axios POST request如何从 Axios POST 请求中返回 18 个字符的字符串响应
【发布时间】:2020-01-15 10:29:22
【问题描述】:

我正在尝试发出返回添加项目 ID 的 POST(添加)请求。 ID 是一个 18 个字符的字符串。只要字符串不超过 16 个字符,一切正常。当长度为 18 个字符时,最后两个字符总是损坏,因为它们默认为零。

我使用 Vuejs 作为前端,使用 SpringBoot 作为后端。我知道一个 Long 的 53 位精度的 javascript 限制,这就是为什么我使用 String 作为我的这个 ID 的类型。如果我试图返回一个 18 位数字而不是 18 个字符的字符串,我希望会发生这种情况。看来,虽然我返回了一个类型 STRING,但 Axios 会自动将其转换为 LONG,这会导致它被损坏。我如何告诉 Axios 不要这样做? ## 标题##谢谢。

=========后端restcontroller端点=============

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

==============前端Axios POST调用===================

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));

========== 控制台输出:=============

以下行是来自我的前端 Post 调用的 console.log 打印语句。这表明我收到了 ID,最后两位数字为零。

帖子的回复是:622056030329638900


请注意,response.data(下面的第 3 行)以 900 结尾,并且没有被引号包围。如果您进一步阅读 - response.request.response(第 10 行和第 11 行)以 912 结尾,这是正确的响应。我想我知道它们为什么不匹配(Axios 将其转换为 Long 并且它被 53 位精度限制破坏)但我不明白为什么 Axios 首先将 String 转换为 Long。


  1. {data: 622056030329638900, status: 200, statusText: "", headers: {…}, config: {…}, …}
  2. 配置:{url:“http://localhost:xxxx/persons”,方法:“post”,数据:“{“firstName”:“daffy”,“middleName”:“woddle”,“lastName”:“duck”,“homeEmail” ":"daffy@gmail.com"}",标题:{...},transformRequest:Array(1),...}
  3. 数据:622056030329638900
  4. 标头:{content-length: "18", content-type: "application/json;charset=UTF-8"}
  5. 请求:XMLHttpRequest
  6. onabort:ƒ handleAbort()
  7. onerror: ƒ handleError()
  8. 加载:空
  9. onloadend: null
  10. onloadstart:空
  11. 进行中:空
  12. onreadystatechange: ƒ handleLoad()
  13. ontimeout: ƒ handleTimeout()
  14. 就绪状态:4
  15. 回复:“622056030329638912”
  16. 响应文本:“622056030329638912”
  17. 响应类型:“”
  18. 响应网址:“http://localhost:xxxx/persons
  19. responseXML:空
  20. 状态:200
  21. 状态文本:“”
  22. 超时:0

预期结果:发送的所有 18 个字符都与接收的字符匹配。 实际结果:前16个字符匹配,后两个为零。

【问题讨论】:

  • 为什么不使用 responseText?
  • 您的 API 返回的数据是否正确?
  • content-type: "application/json;charset=UTF-8"。响应正文被解析为 JSON,因此如果没有引号,它将被转换为数字。另请参阅 axios 的 responseType 设置。
  • 尝试使用Axios的“拦截器”
  • 我将研究拦截器和 responseType - 首选是实现它,因此 response.data 与使用 responseText 相比是有效的

标签: javascript spring spring-boot vue.js axios


【解决方案1】:

问题最终归结为这样一个事实,像“12334”这样的字符串不是有效的 JSON 字符串(而是有效的 JSON 编号)。 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默认是这样转换响应的(解析json):

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

如果您有以下选择:

一:返回一个有效的 Json 字符串,如下所示:"\"622056030329638912\""(服务器端的 JSON ENCODE)

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

二:在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));

【讨论】:

    【解决方案2】:

    这个数字 (622056030329638912) 对于 JavaScript 来说太大了。看一下Number.MAX_SAFE_INTEGER,值为9007199254740991。任何大于 max safe integer 的数字都不能安全地用作浏览器中的数字。

    如果可以的话,把它当作一个字符串。如果您必须使用response.data,请让您的 API 返回一个字符串值。否则,使用responseText 应该没问题。

    MAX_SAFE_INTEGER 常量的值为 9007199254740991(9,007,199,254,740,991 或约 9 万亿)。该数字背后的原因是 JavaScript 使用 IEEE 754 中指定的双精度浮点格式数字,并且只能安全地表示介于 -(2^53 - 1) 和 2^53 - 1 之间的数字。

    在这种情况下,安全是指准确表示整数并正确比较它们的能力。例如, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 将评估为真,这在数学上是不正确的。有关详细信息,请参阅 Number.isSafeInteger()。

    这是一个演示:

    console.log(Number.MAX_SAFE_INTEGER);
    console.log(622056030329638922);

    【讨论】:

      【解决方案3】:

      尝试在后端使用对象返回:

      {value: "622056030329638900"}
      

      这对我有用!

      【讨论】:

      • 是的,我的对象也没有遇到这个问题 - 现在我明白了原因
      • @fivemikes 使用响应处理不是一个好习惯。想象一下,您的应用程序总是在查看数据类型的标头,这将影响性能。您应该清楚自己的期望,因此最好返回一个对象!
      猜你喜欢
      • 2022-01-10
      • 1970-01-01
      • 2019-03-30
      • 2023-04-05
      • 2018-09-19
      • 1970-01-01
      • 2014-11-30
      • 1970-01-01
      • 2020-11-19
      相关资源
      最近更新 更多