Ajax 传输 JSON 与 XML:千古前端教程的数据交换与解析实战

原创2026-09-30 14:03:39212 阅读
文章标签:文档教程前端

Ajax 传输 JSON 与 XML:千古前端教程的数据交换与解析实战

导读

在 Ajax 应用中,服务器返回的数据主要有两种承载格式:JSON 与 XML。本篇是「千古前端图文教程」异步编程系列的核心实战章节,承接 《02-Ajax 入门和发送 http 请求》 中关于 XMLHttpRequest 对象五步请求的基础,深入讲解如何在浏览器端接收、解析并渲染 JSON 与 XML 数据。读完本篇,你将掌握 JSON 与 XML 两种格式的语法规则、JavaScript 与 PHP 两侧的序列化/反序列化方法,以及通过 XMLHttpRequest 完整请求并解析这两种数据格式的前后端联调方案。


一、前置知识:Ajax 的数据从哪来

在进入 JSON 与 XML 之前,先回顾一下 Ajax 的基础链路。Ajax(Asynchronous JavaScript And XML)的核心是 JS 对象 XMLHttpRequest,发送一次请求需要五步:

  1. 创建异步对象 new XMLHttpRequest();
  2. 用 open(method, url, async) 设置请求参数;
  3. 用 send() 发送请求;
  4. 注册 onreadystatechange 事件;
  5. 服务端响应后,通过判断 readyState == 4 && status == 200 获取返回的数据。

其中,与数据格式直接相关的两个属性是(详见 02-Ajax 入门和发送 http 请求):

  • responseText:获得字符串形式的响应数据;
  • responseXML:获得 XML 形式的响应数据。

如果响应的是普通字符串(包括 JSON 字符串),就使用 responseText;如果响应的是 XML,则使用 responseXML。本篇的所有实战都将围绕这两个属性展开。


二、Ajax 传输 JSON

2.1 JSON 的语法

JSON(JavaScript Object Notation):是 ECMAScript 的子集,作用是进行数据的交换。相比其他数据格式,JSON 语法更为简洁,网络传输、机器解析都更为迅速。

语法规则:

  • 数据在键值对中;
  • 数据由逗号分隔;
  • 花括号保存对象;
  • 方括号保存数组。

数据类型:

  • 数字(整数或浮点数);
  • 字符串(在双引号中);
  • 逻辑值(true 或 false);
  • 数组(在方括号中);
  • 对象(在花括号中);
  • null。

示例:

// 对象
{
  "name":"fox",
  "age":"18",
  "sex":"true",
  "car":null
}

// 数组
[
  {
      "name":"小小胡",
      "age":"1"
  },
  {
      "name":"小二胡",
      "age":"2"
  }
]

注意:JSON 中字符串必须使用双引号,键名同样使用双引号包裹,这与 JavaScript 对象字面量的写法略有差异。

2.2 JavaScript 中:json 字符串 <--> js 对象

基本上,所有的语言都有将 json 字符串转化为该语言对象的语法。在 JS 中,主要通过 JSON 内置对象的两个方法完成双向转换:

(1)JSON.parse():将 JSON 字符串转化为 js 对象。

// 将 JSON 字符串格式化为 js 对象
var jsObj = JSON.parse(ajax.responseText);

JSON.parse() 会严格校验传入的字符串,如果字符串不符合 JSON 语法(例如键名漏掉双引号、末尾多一个逗号),会抛出 SyntaxError,因此在实际项目中通常建议用 try...catch 包裹。

(2)JSON.stringify():将 JS 对象转化为 JSON 字符串。

var Obj = {
    name: 'fox',
    age: 18,
    skill: '撩妹',
};

console.log(Obj);

// 将 js 对象格式化为 JSON 字符串
var jsonStr = JSON.stringify(Obj);

JSON.stringify() 常用于向服务器提交数据前的序列化,也常用于调试打印——本项目其他章节(如 04-JavaScript基础/18-数组简介.md、19-数组的常见方法.md)中大量使用 console.log(JSON.stringify(arr)) 来直观查看数组内容,就是这个方法最常见的用法。

2.3 PHP 中:json 字符串 <--> 变量

服务端语言同样具备 JSON 双向转换能力。以 PHP 为例:

  • json_decode() 方法:将 json 字符串转化为变量;
  • json_encode() 方法:将变量转化为 json 字符串。

代码举例:

<?php
    header("Content-Type:text/html;charset=utf-8");
    // json字符串
    $jsonStr = '{"name":"itcast","age":54,"skill":"歌神"}';
    // 字符串转化为 php对象
      print_r(json_decode($jsonStr));

      echo "<br>";
      // php数组
      $arrayName = array('name' =>'littleFox' ,'age' => 13 );
      // php对象 转化为 json字符串
      print_r(json_encode($arrayName));
 ?>

输出结果:

	stdClass Object ( [name] => itcast [age] => 54 [skill] => 歌神 )
	{"name":"littleFox","age":13}

从输出可以看到,json_decode() 默认把 JSON 对象解析为 PHP 的 stdClass 对象,而 json_encode() 会把 PHP 数组序列化为标准的 JSON 字符串——这正是 Ajax 前后端联调时数据流通的完整闭环:PHP 端用 json_encode() 把数组转成 JSON 字符串输出,浏览器端用 JSON.parse() 把 responseText 还原成 JS 对象。

2.4 ajax 请求解析 json(完整举例)

下面通过三个文件,演示一次完整的「PHP 读取 JSON 文件 → Ajax 请求 → 解析并渲染」流程。

(1)Person.json(存放数据的 JSON 文件):

{
    "name": "小强",
    "skill": "砍树",
    "friend": "老板"
}

(2)myJson.php(服务端脚本:读取 json 文件并原样返回):

<?php

	// 读取json文件 并返回即可
	echo  file_get_contents('info/Person.json');

 ?>

这里用到了 PHP 内置的 file_get_contents() 方法读取同目录下 info/Person.json 文件的内容,并通过 echo 直接输出。由于 JSON 本身就是字符串,不需要额外设置响应头,浏览器端按字符串接收即可。

(3)getJson.html(前端页面:发起 Ajax 请求,解析并渲染数据):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    <body>
        <h1>获取 json 数据</h1>
        <input type="button" value="获取json" id="btnJson" />
    </body>
</html>
<script type="text/javascript">
    // 获取的是一个 如果要获取多个
    // document.querySelectorAll(selector)
    document.querySelector('#btnJson').onclick = function () {
        var ajax = new XMLHttpRequest();

        ajax.open('get', 'myJson.php');

        ajax.send();

        ajax.onreadystatechange = function () {
            if (ajax.readyState == 4 && ajax.status == 200) {
                // json 字符串 是字符串 所以我们可以 通过  responseText获取
                console.log(ajax.responseText);

                // 转化为 js对象
                var jsObj = JSON.parse(ajax.responseText);

                console.log(jsObj);

                // 拼接ul s
                var str = '';

                str += '<ul>';
                str += '<li>' + jsObj.name + '</li>';
                str += '<li>' + jsObj.skill + '</li>';
                str += '<li>' + jsObj.friend + '</li>';
                str += '</ul>';

                // 设置到界面上

                document.body.innerHTML = str;
            }
        };
    };
</script>

要点解读:

  1. 由于 JSON 在网络上传输时本质上就是一串文本,所以服务端返回的 JSON 内容统一通过 responseText 获取;
  2. 拿到字符串后,必须用 JSON.parse() 转成 JS 对象,才能用 jsObj.name 这样的点语法读取属性;
  3. 最后通过字符串拼接生成 <ul> 列表,写入 document.body.innerHTML 完成页面渲染;
  4. 这里的判断条件 readyState == 4 && status == 200 是 Ajax 数据完整返回的标准判据:readyState 为 4 表示请求已完成且响应就绪,status 为 200 表示请求成功(这两个状态码的详细含义见 02-Ajax 入门和发送 http 请求)。

三、Ajax 传输 XML

3.1 XML 语法

XML(Extensible Markup Language):可扩展标记语言。与 JSON 不同,XML 的语法要点如下。

1、XML 声明:

<?xml version="1.0" encoding="UTF-8"?>

第一行的声明,指定了 XML 版本(1.0)以及使用的编码。声明必须放在 XML 文档的第一行。

2、自定义标签:

XML 中没有默认的标签,所有的标签都是我们自己定义的。例如:

<fox></fox>
<name></name>

注意:XML 中没有单标签,都是双标签,即必须成对出现(<标签></标签>),标签必须正确嵌套。

3、根节点:

XML 中必须要有一个根节点,所有的子节点都放置在根节点下。例如:

<root1>
  <name></name>
</root1>

XML 文档有且仅有一个根节点,它是整个文档的顶层容器。

3.2 XML 解析

因为 XML 就是标签,所以我们可以直接用解析 Dom 元素的方法解析 XML。浏览器会将 XML 文档解析为一个 document 类型的节点树,天然支持 DOM 查询 API。

解析过程:

(1)html 部分(包含 xml 片段):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    <body>
        <person id="personXML">
            <name>fox</name>
            <age>18</age>
            <skill>小花花</skill>
        </person>
    </body>
</html>

(2)解析 xml:

<script type="text/javascript">
    var xmlObj = document.getElementById('personXML');
    var name = xmlObj.getElementsByTagName('name')[0].innerHTML;

    console.log(name);
</script>

解析思路:先用 getElementById('personXML') 定位 XML 的根节点,再通过 getElementsByTagName('name')[0] 获取第一个 name 标签节点,读取其 .innerHTML 得到标签内的文本内容。整个过程与操作普通 HTML DOM 完全一致。

3.3 ajax 请求解析 xml(完整举例)

与 JSON 请求不同,服务端返回 XML 时必须显式设置响应头 Content-Type 为 text/xml,浏览器才能正确识别并按 XML 文档解析,从而让 responseXML 属性可用。

(1)get_xml.php(服务端脚本:里面包含了 xml 文件):

<?php
	// 设置 返回的为 xml
	header('content-type:text/xml; charset= utf-8');

	// 读取xml文件 并返回
	echo file_get_contents('info/star.xml');

 ?>

上方代码解释:

  • PHP 自带了读取 xml 文件的方法(file_get_contents());
  • 在 PHP 中,如果要使用 XML 传输数据,则需要使用 header() 设置返回的内容为 XML。这里 header('content-type:text/xml; charset=utf-8') 的作用是向浏览器发送响应报文头,声明响应体是 XML 格式。关于 header() 函数设置响应头的更多用法(如设置编码、页面跳转、刷新间隔),可以参见 00-服务器分类及PHP入门.md 中的「php 中的 header() 函数」小节。

(2)get_xml.html(Ajax 请求,获取并解析 xml):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    <body>
        <input type="button" value="获取XMl数据" id="getXML" />
    </body>
</html>
<script type="text/javascript">
    document.querySelector('#getXML').onclick = function () {
        var ajax = new XMLHttpRequest();

        ajax.open('get', 'get_XMl.php');

        ajax.send();

        ajax.onreadystatechange = function () {
            if (ajax.readyState == 4 && ajax.status == 200) {
                // 如果 返回的是 xml文件
                console.log(ajax.responseText);

                // 异步 对象中 有另外一个属性 用来专门获取 xml
                // xml对象 在浏览器段 就是一个 document对象
                // 解析时 可以直接使用 querySelector 或者 getElementById等等 document对象 有的语法
                console.log(ajax.responseXML);
                console.log(ajax.responseXML.querySelector('kuzi').innerHTML);
                // 下面这个 页面文档对象 如果要获取某个标签
                console.log(window.document);
            }
        };
    };
</script>

要点解读:

  1. ajax.responseText 拿到的是 XML 的原始字符串,可以看到标签形式的文本内容;
  2. ajax.responseXML 拿到的是浏览器解析后的 XML Document 对象,它和 window.document 一样是 document 类型,因此可以直接使用 querySelector()、getElementById()、getElementsByTagName() 等 DOM 查询语法来定位节点;
  3. ajax.responseXML.querySelector('kuzi').innerHTML 演示了用选择器直接取出某个子标签的文本内容。

3.4 responseText 与 responseXML 的适用场景

结合两个实战可以总结出规律:

响应类型 获取属性 解析方式 服务端要求
JSON responseText JSON.parse() 转成 JS 对象 输出合法 JSON 字符串即可
XML responseXML 直接当作 document 对象,用 DOM API 查询 必须用 header('content-type:text/xml; charset=utf-8') 声明 XML

如果服务端没有正确设置 XML 的响应头,responseXML 可能返回 null,此时只能退而求其次用 responseText 拿到字符串、再用 DOMParser 自行解析。因此,前后端对数据格式的约定(响应头、编码、结构)是整个联调能否成功的关键。


四、JSON 与 XML 的对比与选型

通过本篇两个实战,可以总结出两种格式的核心差异:

JSON 的优势:

  • 语法简洁,体积更小,网络传输和机器解析更快(这正符合 2.1 节所说的设计初衷);
  • 与 JavaScript 对象天然接近,JSON.parse() / JSON.stringify() 双向转换零成本;
  • 所有主流语言(PHP 的 json_decode / json_encode 等)都内置了完整的序列化支持。

XML 的优势:

  • 可扩展性强,标签语义化,适合表达层级复杂的文档型数据;
  • 有严格的语法约束(唯一根节点、双标签、声明),可配合 DTD/Schema 做数据校验;
  • 在 RSS 订阅、配置文件、SVG 等领域仍是标准格式。

在当前的 Web 开发实践中,接口数据交换几乎都以 JSON 为主,XML 更多出现在文档类场景。另外需要注意:当接口数据涉及跨域时,浏览器默认不允许 Ajax 跨域获取数据,常见的解决方案有 JSONP(利用 <script> 标签的 src 可跨域特性,由服务端返回预定义的函数调用)等,这部分内容可以继续阅读本系列的 《04-同源和跨域》。


五、常见问题排查清单

结合本篇三个示例,罗列几个最容易踩的坑:

  1. JSON.parse() 报错:服务端返回的不是合法 JSON(如键名用了单引号、包含注释、出现尾逗号),或返回了 HTML 错误页。先用 console.log(ajax.responseText) 检查原始字符串。
  2. jsObj.name 拿到 undefined:JSON 键名与代码中读取的属性名不一致(注意 JSON 键名区分大小写),或 JSON 实际是数组而非对象。
  3. responseXML 为 null:服务端没有用 header('content-type:text/xml; charset=utf-8') 声明 XML 响应头,导致浏览器没有按 XML 解析响应体。
  4. 中文乱码:XML 声明中的 encoding、服务端 header() 中的 charset、页面的 <meta charset> 三者编码必须统一为 UTF-8。
  5. readyState 判断遗漏:务必在 onreadystatechange 中同时判断 readyState == 4 && status == 200,否则可能在数据尚未完整返回时就提前取值。

小结

本篇以「千古前端图文教程」中 Ajax 传输 JSON 与 XML 的实战为主线,完整覆盖了两种数据格式的语法规则、JavaScript 与 PHP 两侧的转换方法,以及基于 XMLHttpRequest 的前后端联调示例。掌握 JSON.parse / JSON.stringify、PHP 的 json_decode / json_encode,以及 responseText / responseXML 两个属性的正确使用场景,你就能独立完成绝大多数 Ajax 数据交互需求。后续进阶可继续学习本系列的 《05-回调函数》 与 《06-Promise 入门详解》,用更优雅的方式组织异步请求逻辑。

登录后查看全文
Web