非必填情况下,signInfo字段中经过JSON.stringify
后的字符串对象缺少value
key,导致后端parse之后无法正确读取value值,进而报接口系统异常,用户无法进行下一步动作。
// 异常入参数据,数组字符串中没有value key
{
signInfo: '[{"fieldId":539},{"fieldId":540},{"fieldId":546,"value":"10:30"}]'
}
// 正常入参数据
{
signInfo: '[{"fieldId":539,"value":"银卡"},{"fieldId":540,"value":"2021-03-01"},{"fieldId":546,"value":"10:30"}]'
}
异常数据是如何产生的
// 默认情况下数据是这样的
let signInfo = [
{
fieldId: 539,
value: undefined
},
{
fieldId: 540,
value: undefined
},
{
fieldId: 546,
value: undefined
},
]
// 经过JSON.stringify之后的数据,少了value key,导致后端无法读取value值进行报错
// 具体原因是`undefined`、`任意的函数`以及`symbol值`,出现在`非数组对象`的属性值中时在序列化过程中会被忽略
console.log(JSON.stringify(signInfo))
// '[{"fieldId":539},{"fieldId":540},{"fieldId":546}]'
解决方案
问题的原因找到了,解决方式 「(这里只讲前端的解决方案,当然也可以由后端解决)」 也很简单,将value值为undefined的项转化为空字符串再提交即可。
方案一:新开一个对象处理
let signInfo = [
{
fieldId: 539,
value: undefined
},
{
fieldId: 540,
value: undefined
},
{
fieldId: 546,
value: undefined
},
]
let newSignInfo = signInfo.map((it) => {
const value = typeof it.value === 'undefined' ? '' : it.value
return {
...it,
value
}
})
console.log(JSON.stringify(newSignInfo))
// '[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'
方案二:利用JSON.stringify
第二个参数,直接处理
方案一的缺陷是需要新开一个对象进行一顿操作才能解决,不够优雅
let signInfo = [
{
fieldId: 539,
value: undefined
},
{
fieldId: 540,
value: undefined
},
{
fieldId: 546,
value: undefined
},
]
// 判断到value为undefined,返回空字符串即可
JSON.stringify(signInfo, (key, value) => typeof value === 'undefined' ? '' : value)
// '[{"fieldId":539,"value":""},{"fieldId":540,"value":""},{"fieldId":546,"value":""}]'
总结:
重新审视一下JSON.stringify
这个方法,彻底搞清楚转换规则,并尝试手写实现一个JSON.stringify
JSON.stringify()
方法将一个 JavaScript对象
或值
转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。
JSON.stringify(value[, replacer [, space]])
参数[1]
-
value
将要序列化成 一个 JSON 字符串的值。
-
replacer
可选-
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;
-
如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
-
如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
-
-
space
可选-
指定缩进用的空白字符串,用于美化输出(pretty-print);
-
如果参数是个数字,它代表有多少的空格;上限为10。
-
该值若小于1,则意味着没有空格;
-
如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;
-
如果该参数没有提供(或者为 null),将没有空格。
-
「返回值」
一个表示给定值的JSON字符串。
异常[2]
-
当在循环引用时会抛出异常
TypeError
("cyclic object value")(循环对象值) -
当尝试去转换
BigInt
类型的值会抛出TypeError
("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化). -
「注意」
-
JSON.stringify可以转换对象或者值(平常用的更多的是转换对象)
-
可以指定
replacer
为函数选择性的地替换 -
也可以指定
replacer
为数组,可转换指定的属性