一个粗心的Bug,JSON格式不规范导致AJAX错误
一、事件回放
今天工作时碰到了一个奇怪的问题,这个问题很早很早以前也碰到过,不过没想到过这么久了竟然又栽在这里。
当时正在联调一个项目,由于后端没有提供数据接口,于是我直接本地建立了一个 json 文件,然后把配置的URL指向这个json文件,文件内容大概如下 :
// account.json{
success: true,
data: [{
id: "1",
name: "张XX",
job: "员工",
type: 1
}]
}
嗯,一个十分标准的Javascript对象。
然后,我的ajax代码大概如下:
function getRemoteData(url, param, success) {
$.ajax({
type: 'get',
url: url,
data: param,
dataType: 'json',
cache: false,
success: function(result) {
success(result);
},
error: function() {
alert('网络错误,请重试');
}
});
}
然后,悲剧就开始了。
这段代码,一直走入error的回调
什么原因?我开始漫漫的排查之路。
一开始,我想是不是ajax代码写错了,仔细看了看,貌似没有什么问题。
然后,由于是我使用本地json文件导致的问题,所以一直觉得是本地文件这一块出的问题。
突然想到了貌似浏览器有个对于本地文件访问的安全限制,比如chrome就有这个限制,需要在启动的时候加上参数。
但是印象中这种情况控制台会有提示的,所以应该不是这种情况,
不过我还是死马当作活马医,试一试看看,给浏览器加上了启动参数
--allow-file-access-from-files
结果,确实没用。
打开浏览器的Network,排查,发现了一个奇怪现象
在preview里面看数据
我的那句 success: true 怎么会变成 undefined: true。这是什么鬼。。。于是思路转向了json文件方向。
然后又想,会不会是返回的数据不是json导致的?(其实这次已经接近正确答案了),
但是我看了看文件,并没有发现什么问题,
所以猜然道是浏览器把我的json文件当作文本文件,而我dataType写了json导致解析错误?(哭!!!感觉当时应该是脑抽了)
然后修改ajax代码
function getRemoteData(url, param, success) {
$.ajax({
type: 'get',
url: url,
data: param,
dataType: 'text', // 改成了text
cache: false,
success: function(result) {
success(eval('(' + result + ')')); // 使用eval解析了一下 },
error: function() {
alert('网络错误,请重试');
}
});
}
果然,运行成功了。
但是,这还是治标不治本啊,而且也不能 每次 切换接口的时候改代码吧。
然后,深吸一口气,决定好好静下来想想这个问题。
首先看了看自己以前的代码,发现也是这么写的,完全没问题。。
不信邪,,看了看同事的代码,写法不一样,但是大体上也是这样的,也没问题。
那到底是什么问题,崩溃啊!
一怒之下,打开stackoverflow,开始搜索
由于方向错误,一直搜索 ajax、local file、always error等等。。
我只能说当时我的内心是崩溃的,虽然在搜索的过程中,学到了好多别的知识(各种问题链接看来看去,最后竟然看到关于react的东西去了,时间就是这样流逝掉的。。。),但关键是我这个问题还是没有解决。
根据经验,往往最无厘头的问题原因往往是最简单的,心想这一定是一个很小的错误照成的,但是错误在哪里呢?
终于,功夫不负有心人,我找到了,因为那个json文件格式错了。。
在jQuery的api网站上看到了这么一句话
在 jQuery 1.4 中,JSON 格式的数据以严格的方式解析,如果格式有错误,jQuery都会被拒绝并抛出一个解析错误的异常。(见json.org的更多信息,正确的JSON格式。)
于是乎,我改了下文件
// account.json{ "success": true, "date": [{ "id": "1", "name": "张XX", "job": "员工", "type": 1
}]
}
好吧,运行成功了。
不知道各位看到了文件的区别吗。标准的JSON,所有的key,是需要引号的。
就是这么一个小小的问题!
二、标准JSON格式
虽然问题解决了,但是这次的经历让我有点劫后余生的感觉,做了这么多年的前端,尽然连一个JSON都掌握不了?实在说不过去。
于是进入了JSON官网(http://json.org/json-zh.html),把那一屏半的内容好好的看了看。
都说细节是魔鬼,以前一直潜意识的就把Javascript对象当作JSON的我,这次真的好好补习了下JSON的知识。
有几个点可以和大家分享下
1、对象的key一定要用双引号。
这个就是我今天碰到的问题,就不多说了。
2、对象的value可以有以下几种值。
大体上和Javascript对象没区别。
但是这里要注意的一点是,没有undefined。
也就是说
{ "success": undefined
}
这么一个JSON,是错误的。
3、对于number类型,表示的方法如下
用科学计数法的时候会牵涉到。
三、一点感想
回头看这个bug,真的是非常非常基础。本来解决完也就没事了,但这次却让我陷入了沉思。
记得以前有人调侃过,是说前端分太细了,CSS和Javascript都分开,以后是不是要分一个JSON工程师啊。
虽然只是一句调侃,但是我想大部分前端对于JSON都抱着一种“哦,就是一个Javascript对象”这种态度,而没有去认真去看一看它的定义。
回想最近两年学习与接触的前端知识,各种工程化工具,各种MV*框架,前端应用架构模式等。而那些基础的东西确实很久没有关注了。
其实之前我一直觉得自己基础还挺好的,从11年入行以来,泡着蓝色理想论坛 ,HTML,CSS一步一步走过来,也算踏实。
又想起前不久阿当舌战群儒,争论关于前端基础和层出不穷的新技术问题。虽然不能说完全认可他的观点,但是现在也挺能理解。
是时候好好静下来,重拾那些前端最根本的东西了。
- HDUOJ-------1753大明A+B(大数之小数加法)
- HDUOJ---1754 I Hate It (线段树之单点更新查区间最大值)
- HDUOJ----1166敌兵布阵(线段树单点更新)
- poj----2155 Matrix(二维树状数组第二类)
- poj------2352 Stars(树状数组)
- HDUOJ-----2852 KiKi's K-Number(树状数组+二分)
- nyoj----522 Interval (简单树状数组)
- HDUOJ-----2838Cow Sorting(组合树状数组)
- HDUOJ---2642Stars(二维树状数组)
- HDUOJ -----Color the ball
- poj-----Ultra-QuickSort(离散化+树状数组)
- HDUOJ---1241Oil Deposits(dfs)
- HDUOJ------2398Savings Account
- HDUOJ-----2399GPA
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 神经网络架构搜索——二值可微分搜索(BATS)
- UEFI 原理与编程 1 - UEFI开发环境EDK2搭建
- 【Unity】瞎做个宝石迷阵吧!(1)——构建场景
- VUE组件传值案例讲解
- 【JAVA】来写个JAVA的HelloWorld吧!
- 如何发布自己的项目到Maven中央仓库?
- 《闲扯Redis八》Redis字典的哈希表执行Rehash过程分析
- 为什么说在Android中请求权限从来都不是一件简单的事情?
- 小知识:如何赋予用户查看所有存储过程和触发器的权限
- ZCU106使用VCU TRD的MIPI的例子
- 一款功能简约到可怜的SQL 客户端
- Kotlin---data class
- sqlmap的使用方法
- 从0开始做播放器---音频播放有杂音且音调异常
- 线上故障实录-一大早服务就不可用了?