节点请求模块:将 XML 解析为 JSON

node request module: parsing XML as JSON

直到最近我一直在使用 node request 模块获取 XML 数据,然后 运行 通过 XML 到 JSON转换器。我偶然发现,如果我将 json: true 设置为选项(即使知道端点 returns XML,而不是 JSON),我实际上是在返回 JSON:

var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'Whosebug question ( } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
request(options, function (error, response, body) {
    console.log(`body for ${options.uri}: ${JSON.stringify(body)}`);
});

上面调用returns JSON,而raw URL实际上是发送XML。果然,json: false returned 数据是 XML:

var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'Whosebug question ( } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
options.json = false; // <<--- the only difference in the request
request(options, function (error, response, body) {
    console.log(`body for ${options.uri}: ${body}`);
});

所以我想 "that's handy",直到我用 different URL that also returns XML 尝试了同样的技巧,在这种情况下,尽管使用了 returned 数据仍然是 XML相同的请求选项:

var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'Whosebug question ( } };
options.uri = 'https://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php?whichClient=NDFDgen&lat=40.597&lon=-74.26&product=time-series&temp=tempSubmit=Submit';
request(options, function (error, response, body) {
    console.log(`body for ${options.uri}: ${body}`);
});

这里有什么区别?如何获得后一个请求 return JSON 格式的数据(这样我就可以避免自己将 XML 转换为 JSON 的步骤)?也许第一个示例中的端点可以检测到 JSON 被请求,它实际上是 return JSON 而不是 XML?

EDIT 奇怪的是,第一个请求现在 returning XML 而不是 JSON 即使 json: true。所以也许这种行为取决于从端点发送的内容,甚至自从我几个小时前发布以来他们已经改变了这一点

所以现在行为是不可重复的,答案对你的特定问题不太有用,但我认为值得指出的是,当你在 request 模块上设置 json:true 时,它确实为您提供一些幕后花絮:

  • 将接受 header 设置为 'application/json'
  • 使用 JSON.parse()
  • 解析响应 body
  • 带有 body 的请求类型也会自动将 body 序列化为 JSON
  • 带有 body 的请求类型也会得到 Content-Type header 添加为 'application/json'

所以也许他们确实改变了它,但我看到有很多 Web 服务会检测 content-type 以根据接受 header 发送并适当地响应某些集合有意义的类型(通常是 XML 或 JSON,但有时是 CSV、TXT、HTML 等)。

为了处理 XML 查询,我通常使用请求模块做这样的事情:

import parser from "xml2json";
const resp = await rp({
  method: "POST",
  url: 'some url',
  form: {xml_query}, // set XML query to xml_query field
});
const parsedData = parser.toJson(resp, {
  object: true, // returns a Javascript object instead of a JSON string
  coerce: true, // makes type coercion.
});