做前端开发或者写接口对接的时候,经常会遇到一种让人头大的数据结构——JSON多层嵌套。比如你从后台拿到一段数据,展开一看,里面套着对象,对象里又套数组,数组里还有对象,一层接一层,看得眼花缭乱。
一个真实的场景
前几天我帮同事调一个用户信息接口,返回的数据长这样:
{
"status": "success",
"data": {
"user": {
"id": 1001,
"name": "张伟",
"profile": {
"age": 28,
"address": {
"city": "杭州",
"district": "西湖区"
}
},
"orders": [
{
"order_id": "O20240401001",
"items": [
{ "product": "咖啡机", "price": 599 }
]
}
]
}
}
}
想取用户的所在城市?得这么写:response.data.user.profile.address.city。要是哪一层拼错了,或者某个字段是 null,程序就可能直接报错。
怎么安全地读取嵌套数据?
直接用点操作符风险太高。更稳妥的做法是加判断,比如:
let city = response && response.data && response.data.user &&
response.data.user.profile && response.data.user.profile.address ?
response.data.user.profile.address.city : null;
虽然啰嗦,但至少不会崩溃。不过写多了真的累。
现在很多人会用解构赋值配合默认值来简化:
const { data: { user: { profile: { address: { city } = {} } = {} } = {} } = {} } = response;
看起来有点绕,但一旦习惯,写起来还挺顺手。记得给每一层可能缺失的对象设空对象默认值,避免引用错误。
工具函数也能帮大忙
如果你经常处理这种结构,可以封装一个取值函数:
function get(obj, path, defaultValue = null) {
const keys = path.split('.');
let result = obj;
for (let key of keys) {
if (result == null || typeof result !== 'object') return defaultValue;
result = result[key];
}
return result !== undefined ? result : defaultValue;
}
// 使用方式
const city = get(response, 'data.user.profile.address.city');
路径写成字符串,清晰又不容易出错。类似的方法在 lodash 里也有,叫 _.get,可以直接用。
嵌套太深?可能是设计问题
有时候数据嵌得太深,不是代码的问题,而是接口设计可以优化。比如“订单里的商品”本可以扁平化处理,没必要层层包裹。跟后端同事沟通一下,看看能不能调整结构,减少不必要的层级。
另外,前端展示时也可以考虑做一次数据整理,把常用字段提前:
const userInfo = {
name: response.data.user.name,
city: response.data.user.profile.address.city,
latestOrder: response.data.user.orders[0]?.order_id
};
这样后续用起来就轻松多了。
JSON多层嵌套并不可怕,关键是怎么应对。掌握几种取值技巧,再结合实际业务调整数据结构,慢慢就习惯了。