如何使用 axios 在响应中将字符串转换为数字?

How can I cast a string to number in an response using axios?

我正在使用 Axios 对 public API 执行 GET 请求。这 API return 一个数值作为字符串。我需要将此值转换为数值。我的应用程序使用 tsc 运行,所以我希望我的对象的结果是一个数值,但它不是。

Axios 响应

[
  {
    "name": "foo1",
    "value": "8123.3000"
  },
  {
    "name": "foo2",
    "value": "5132.2003"
  },
  {
    "name": "foo3",
    "value": "622.0000"
  }
]

预期输出

[
  {
    "name": "foo1",
    "value": 8123.3
  },
  {
    "name": "foo2",
    "value": 5132.2003
  },
  {
    "name": "foo3",
    "value": 622
  }
]

我的代码很简单,

interface MyObj {
  myString: string;
  myNumber: number;
}

(async () => {
  let { data }: AxiosResponse<MyObj> = await axios.get<MyObj>("/public/data");
  console.log(data);
})();

我尝试使用interfaceclass、界面Number。没有任何效果。

I leave an example of code to try it.

如何在不手动将每个值逐个转换的情况下获得预期的输出?

当声明你的 axios 请求 returns 某种类型时;这将在编译时和语法检查时进行检查。但是它不会在运行时执行此操作。如果您知道 axios 请求返回的内容与您的界面不同,则需要先转换为该格式。您可以使用 JSON.parse 函数的第二个参数来执行此操作,如下所示:

interface Item {
  name: string;
  value: number;
}

let responseString = `
[
  {
    "name": "foo1",
    "value": "8123.3000"
  },
  {
    "name": "foo2",
    "value": "5132.2003"
  },
  {
    "name": "foo3",
    "value": "622.0000"
  }
]`

const items: Item[] = JSON.parse(responseString, (key, value) => {
  const propertiesToCast = ["value"] // Which properties should be converted from string to number
  if (propertiesToCast.includes(key)) {
    return parseFloat(value)
  }
  return value
});

console.log(items)

Axios 不会更改响应中的属性类型。请确认服务器没有向您发送错误的类型。


编辑

从您的评论来看,服务器似乎将 vslue 作为字符串而不是数字发送给您。在这种情况下,我建议使用 Ajv (https://github.com/ajv-validator/ajv),这样您就可以创建一个描述响应外观的模式。 ajv cn 也帮你把值从字符串转成数字:

const Ajv = require('ajv')

const ajv = new Ajv({
  // allow chaning the type of some values from type X to type Y. depends on the source and target type:
  // https://ajv.js.org/guide/modifying-data.html#coercing-data-types
  // X => Y rules: https://ajv.js.org/coercion.html
  coerceTypes: true,
})

const schema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      name: { type: 'string' },
      value: { type: 'number' },
    },
    required: ['name', 'value'],
    additionalProperties: false,
  },
}

const data = { name: 1, value: '1.1' }

console.log(typeof data.value === 'number') // false!

const valid = ajv.validate(schema, data)
if (!valid) {
  console.log(ajv.errors)
  process.exit(1)
}

console.log(typeof data.value === 'number') // true!