はじめに
最近、Node.js + axios の組み合わせでレスポンスボディがXMLで返ってくるWebAPIを呼び出すことがあったので、その時にやったことを書いておきます。
axiosでXMLを扱うには
axiosでレスポンスボディがXMLの場合、次のようにconfig.responseType
に'document'
を指定すると、Documentオブジェクトとして取得することができます。
const url = 'https://status.aws.amazon.com/rss/appsync-ap-northeast-1.rss';
const config = {
responseType: 'document'
};
const response = await axios.get(url, config);
const data = response.data; // data は Documentオブジェクト
ただし、これは実行環境がブラウザの場合でNode.jsの場合はXMLが文字列をとして返ってきます。
XML文字列のままでは困ります。(Documentオブジェクトだとしても扱いやすはないですが...)
やはり、扱い慣れたJSON(JavaScriptオブジェクト)だと嬉しいです。
なので、XMLとJSONに変換してやります。
axiosはconfig.transformResponse
でレスポンスの変換処理をカスタマイズできます。
transformResponseにはレスポンスを変換する関数の配列を設定できます。今回は xml2js でXMLをJSONに変換するようにしました。
コードは以下のようになります。
const axios = require('axios');
const xml2js = require('xml2js');
const fetchXml = async () => {
const config = {
// responseType: 'document', 'document'はブラウザ環境以外ではtextと同じ
transformResponse: [(data) => {
let jsonData;
const parser = new xml2js.Parser({
async: false,
explicitArray: false
});
parser.parseString(data, (error, json) => {
jsonData = json;
});
return jsonData;
}],
};
return await axios.get('https://status.aws.amazon.com/rss/appsync-ap-northeast-1.rss', config);
};
fetchXml()
.then(response => console.log(JSON.stringify(response.data, null, 2)))
.catch(e => console.error(e));
実行結果は、次のようになります。
{
"rss": {
"$": {
"version": "2.0"
},
"channel": {
"title": "AWS AppSync (Tokyo) Service Status",
"link": "http://status.aws.amazon.com/",
"language": "en-us",
"lastBuildDate": "Fri, 05 Jun 2020 00:05:20 PDT",
"generator": "AWS Service Health Dashboard RSS Generator",
"description": "AWS AppSync (Tokyo) Service Status",
"ttl": "5"
}
}
}
まとめ
axiosではtransformResponseでレスポンスの変換処理をカスタマイズできます。この部分でXMLをJSONに変換すれば axios.get() などのレスポンスオブジェクトは変換済みの形式で取得できます。
今回は、xml2jsを使いましたが、XMLをJSONに変換するモジュールは他にも fast-xml-parser などがあるので要件にあったもの選んで使えばいいと思います。ただし、transformResponseに設定する関数は非同期処理を扱えない(Promiseを返したりはできない)ので変換処理が同期的に実行できるモジュールを選ぶ必要があるので注意です。