$.ajax 中的contentType

在 cnodejs.org 论坛中有一个问题,让我也很奇怪,说是 $.ajax 设置数据类型 applicaiton/json之后,服务器端(express)就拿不到数据,好奇之下,就去翻了翻资料,发现了一个自己也没有注意到的事。

于是有了这篇文章。

正文

$.ajax contentType 和 dataType , contentType 主要设置你发送给服务器的格式,dataType设置你收到服务器数据的格式。

在http 请求中,get 和 post 是最常用的。在 jquery 的 ajax 中, contentType都是默认的值:application/x-www-form-urlencoded,这种格式的特点就是,name/value 成为一组,每组之间用 & 联接,而 name与value 则是使用 = 连接。如: wwwh.baidu.com/q?key=fdsa&lang=zh 这是get , 而 post 请求则是使用请求体,参数不在 url 中,在请求体中的参数表现形式也是: key=fdsa&lang=zh的形式。

键值对这样组织在一般的情况下是没有什么问题的,这里说的一般是,不带嵌套类型JSON,也就是 简单的JSON,形如这样:

1
2
3
4
5
{
    a: 1,
    b: 2,
    c: 3
}

但是在一些复杂的情况下就有问题了。 例如在 ajax 中你要传一个复杂的 json 对像,也就说是对象嵌数组,数组中包括对象,兄果你这样传:

1
2
3
4
5
6
7
{
  data: {
    a: [{
      x: 2
    }]
  }
}

这个复杂对象, application/x-www-form-urlencoded 这种形式是没有办法将复杂的 JSON 组织成键值对形式(当然也有方案这点可以参考 ) ,你传进去可以发送请求,但是服务端收到数据为空, 因为 ajax 没有办法知道怎样处理这个数据。

这怎么可以呢?

聪明的程序员发现 http 还可以自定义数据类型,于是就定义一种叫 application/json 的类型。这种类型是 text , 我们 ajax 的复杂JSON数据,用 JSON.stringify序列化后,然后发送,在服务器端接到然后用 JSON.parse 进行还原就行了,这样就能处理复杂的对象了。

1
2
3
4
5
$.ajax({
    dataType: 'json',
    contentType: 'application/json',
    data: JSON.stringify({a: [{b:1, a:1}]})
})

这样你就可以发送复杂JSON的对象了。像现在的 restclient 都是这样处理的

JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,如果指定了replacer是一个函数,则可以替换值,或者如果指定了replacer是一个数组,可选的仅包括指定的属性。

语法

JSON.stringify(value[, replacer [, space]])

参数

value
将要序列化成 一个JSON 字符串的值。
replacer 可选
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为null或者未提供,则对象所有的属性都会被序列化;关于该参数更详细的解释和示例,请参考使用原生的 JSON 对象一文。
space 可选
指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(字符串的前十个字母),该字符串将被作为空格;如果该参数没有提供(或者为null)将没有空格。

返回值

一个表示给定值的JSON字符串。

描述

关于序列化,有下面五点注意事项:

  • 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
  • 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
  • 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
  • 不可枚举的属性会被忽略
JSON.stringify({});                        // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}' JSON.stringify({x: 5, y: 6});
// "{"x":5,"y":6}" JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// '[1,"false",false]' JSON.stringify({x: undefined, y: Object, z: Symbol("")});
// '{}' JSON.stringify([undefined, Object, Symbol("")]);
// '[null,null,null]' JSON.stringify({[Symbol("foo")]: "foo"});
// '{}' JSON.stringify({[Symbol.for("foo")]: "foo"}, [Symbol.for("foo")]);
// '{}' JSON.stringify(
{[Symbol.for("foo")]: "foo"},
function (k, v) {
if (typeof k === "symbol"){
return "a symbol";
}
}
); // undefined // 不可枚举的属性默认会被忽略:
JSON.stringify(
Object.create(
null,
{
x: { value: 'x', enumerable: false },
y: { value: 'y', enumerable: true }
}
)
); // "{"y":"y"}"

replacer参数

replacer参数可以是一个函数或者一个数组。作为函数,它有两个参数,键(key)值(value)都会被序列化。

  • 如果返回一个 Number, 转换成相应的字符串被添加入JSON字符串。
  • 如果返回一个 String, 该字符串作为属性值被添加入JSON。
  • 如果返回一个 Boolean, "true" 或者 "false"被作为属性值被添加入JSON字符串。
  • 如果返回任何其他对象,该对象递归地序列化成JSON字符串,对每个属性调用replacer方法。除非该对象是一个函数,这种情况将不会被序列化成JSON字符串。
  • 如果返回undefined,该属性值不会在JSON字符串中输出。

注意: 不能用replacer方法,从数组中移除值(values),如若返回undefined或者一个函数,将会被null取代。

例子(function)

function replacer(key, value) {
if (typeof value === "string") {
return undefined;
}
return value;
} var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
var jsonString = JSON.stringify(foo, replacer);

JSON序列化结果为 {"week":45,"month":7}.

例子(array)

如果replacer是一个数组,数组的值代表将被序列化成JSON字符串的属性名。

JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', 只保留“week”和“month”属性值。

space 参数

space 参数用来控制结果字符串里面的间距。如果是一个数字, 则在字符串化时每一级别会比上一级别缩进多这个数字值的空格(最多10个空格);如果是一个字符串,则每一级别会比上一级别多缩进用该字符串(或该字符串的前十个字符)。

JSON.stringify({ a: 2 }, null, " ");   // '{\n "a": 2\n}'

使用制表符(\t)来缩进:

JSON.stringify({ uno: 1, dos : 2 }, null, '\t')
// '{ \
// "uno": 1, \
// "dos": 2 \
// }'

toJSON 方法

如果一个被序列化的对象拥有 toJSON 方法,那么该 toJSON 方法就会覆盖该对象默认的序列化行为:不是那个对象被序列化,而是调用 toJSON 方法后的返回值会被序列化,例如:

var obj = {
foo: 'foo',
toJSON: function () {
return 'bar';
}
};
JSON.stringify(obj); // '"bar"'
JSON.stringify({x: obj}); // '{"x":"bar"}'

JSON.stringify用作 JavaScript

注意JSON不是javascript严格意义上的子集,在JSON中不需要省略两条终线(Line separator和Paragraph separator)但在JavaScript中需要被省略。因此,如果JSON被用作JSONP时,下面方法可以使用:

function jsFriendlyJSONStringify (s) {
return JSON.stringify(s).
replace(/\u2028/g, '\\u2028').
replace(/\u2029/g, '\\u2029');
} var s = {
a: String.fromCharCode(0x2028),
b: String.fromCharCode(0x2029)
};
try {
eval('(' + JSON.stringify(s) + ')');
} catch (e) {
console.log(e); // "SyntaxError: unterminated string literal"
} // No need for a catch
eval('(' + jsFriendlyJSONStringify(s) + ')'); // console.log in Firefox unescapes the Unicode if
// logged to console, so we use alert
alert(jsFriendlyJSONStringify(s)); // {"a":"\u2028","b":"\u2029"}

使用 JSON.stringify 结合 localStorage 的例子

一些时候,你想存储用户创建的一个对象,并且,即使在浏览器被关闭后仍能恢复该对象。下面的例子是 JSON.stringify 适用于这种情形的一个样板:

// 创建一个示例数据
var session = {
'screens' : [],
'state' : true
};
session.screens.push({"name":"screenA", "width":450, "height":250});
session.screens.push({"name":"screenB", "width":650, "height":350});
session.screens.push({"name":"screenC", "width":750, "height":120});
session.screens.push({"name":"screenD", "width":250, "height":60});
session.screens.push({"name":"screenE", "width":390, "height":120});
session.screens.push({"name":"screenF", "width":1240, "height":650}); // 使用 JSON.stringify 转换为 JSON 字符串
// 然后使用 localStorage 保存在 session 名称里
localStorage.setItem('session', JSON.stringify(session)); // 然后是如何转换通过 JSON.stringify 生成的字符串,该字符串以 JSON 格式保存在 localStorage 里
var restoredSession = JSON.parse(localStorage.getItem('session')); // 现在 restoredSession 包含了保存在 localStorage 里的对象
console.log(restoredSession);

javascript的常用操作(三)的更多相关文章

  1. 请写出JavaScript中常用的三种事件。

    请写出JavaScript中常用的三种事件. 解答: onclick,onblur,onChange

  2. JavaScript 字符串常用操作

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  3. JavaScript 字符串常用操作纪要

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  4. JavaScript数组常用操作

    前言 相信大家都用惯了jquery或者underscore等这些类库中常用的数组相关的操作,如$.isArray,_.some,_.find等等方法.这里无非是对原生js的数组操作多了一些包装. 这里 ...

  5. mongodb的常用操作(三)

    继续mongodb的学习和总结: 11.mongodb的mapreduce功能 mapreduce可以说是mongodb的一个很强大的功能,可以实现复杂的运算和统计,做一个简要的总结: 假设有user ...

  6. JavaScript数组常用操作总结

    我们在日常开发过程中,使用到原生 JavaScript的时候,有时候会频繁的对数组进行操作,今天我把工作以来,经常用到的有关 JavaScript数组的方法总结一下,方便日后工作的时候查找使用! 一. ...

  7. JavaScript DOM 常用操作

    1.理解DOM: DOM(Document Object Model ,文档对象模型)一种独立于语言,用于操作xml,html文档的应用编程接口. 怎么说,我从两个角度理解: 对于JavaScript ...

  8. javascript的常用操作(一)

    1.  实时监听input的值变化 onchange事件只在键盘或者鼠标操作改变对象属性,且失去焦点时触发,脚本触发无效; 而onkeydown/onkeypress/onkeyup在处理复制.粘贴. ...

  9. javascript中常用操作字符串的几种方法charAt()、indexOf()、slice()、substr()

    一.charAt(index) 返回一个字符串某一个索引的字符. 语法:str.charAt(index); var str='我是中国人'; console.log(str.charAt(3));/ ...

随机推荐

  1. CF1041F Ray in the tube

    挂上Chester大神的解题报告 有一个思维跳跃的地方,就是不应该枚举所有的$B$点,而是应该在选定一个$A$点之后枚举距离计算. 然后我们发现枚举距离是$2^k$的长度就可以了,证明如下: 假如距离 ...

  2. neon eclipse tomcat发布项目乱码

    解决方法如图

  3. 14.Nginx 文件名逻辑漏洞(CVE-2013-4547)

    由于博主在渗透网站时发现现在Nginx搭建的网站是越来越多 所以对Nginx的漏洞来一个全面性的复习,本次从Nginx较早的漏洞开始分析. 2013年底,nginx再次爆出漏洞(CVE-2013-45 ...

  4. hdu1056

    #include <cstdio> void main(){ double length; double l[300]; l[1] = 1.0/2; int i; for (i = 2;; ...

  5. 解决IIS出现的问题

  6. C# 字符串转JSON

    一.简单小结 C# 中 String 转 JSON var items = JsonConvert.DeserializeObject<class>(stringJSON); 这里的 cl ...

  7. Ansible Playbooks基本使用

    你将学到什么 如何使用playbook 如何编写playbook 如何使用roles PlayBook使用 基础环境 ### 64 位 Ubuntu 16.04 LTS,创建CentOS LXC容器w ...

  8. Zookeeper安装和部署

    Zookeeper安装和部署:ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用 ...

  9. 浅谈JavaScript--this指向

    js中this的值取决于调用的模式 方法调用模式 var student={ name:"adoctors", showThis:function(){ console.log(t ...

  10. NYOJ542-试制品

    题目链接:点击打开链接 试 制 品 时间限制:1000 ms  |  内存限制:65535 KB 难度: 描述 ZZ大学的Dr.Kong最近发现实验室的很多试制品都已经用完.由于项目经费有限,为了节省 ...