matsutoba’s blog

フロントエンドエンジニアをしています

axiosで配列形式のパラメータのシリアライズ

axios を使って、ASP.NET Core に配列型のデータを送りたい場合のメモです。

foo[0].bar=1&foo[0].hoge=2&foo[1].bar=3&foo[1].hoge=4

のようなデータを送ります。

qsライブラリで配列形式を変換

qsを使って配列形式を変換する方法を使いました。

まず、元のデータはこのような形です。

import qs from 'qs';
const data = {
  foo: [
    { bar:1, hoge:2 },
    { bar:3, hoge:4 },
  ]
};
console.log(data);
{ foo : [ { bar: 1, hoge: 2 }, { bar: 3, hoge: 4 } ] }

これを qs.stringify で変換すると

import qs from 'qs';
const data = {
  foo: [
    { bar:1, hoge:2 },
    { bar:3, hoge:4 },
  ]
};
// encode: false オプションを指定しないとURLエンコードされた文字列になる
const params = qs.stringify( data, { encode: false } );
console.log(params);
foo[0][bar]=1&foo[0][hoge]=2&foo[1][bar]=3&foo[1][hoge]=4

となり、惜しい形までは来ました。

2番めのカッコの部分を .bar .hoge にしたいのですが、簡単に変換できそうな方法を見つけられなかったので、encoder オプションを使って自力で変換してみました。

import qs from 'qs';
const data = {
  foo: [
    { bar:1, hoge:2 },
    { bar:3, hoge:4 },
  ]
};
const params = qs.stringify( data, 
{ 
  encoder: function (str, defaultEncorder, charset, type) {
    console.log(`Type=${type} Str=${str}`);
    if (type === 'key') {
      if (str.match(/¥[bar][/g)) {
        return str.replace(/¥[bar¥]/g, ".bar");
      }
      if (str.match(/¥[hoge][/g)) {
        return str.replace(/¥[hoge¥]/g, ".hoge");
      }
    }
    return str;
  },
  // encode: false,   // encode:true にすると encoderの関数が実行されないため
} );
console.log(params);
Type=key Str=foo[0][bar]
Type=value Str=1
Type=key Str=foo[0][hoge]
Type=value Str=2
Type=key Str=foo[0][bar]
Type=value Str=3
Type=key Str=foo[0][hoge]
Type=value Str=4
foo[0].bar=1&foo[0].hoge=2&foo[1].bar=3&foo[1].hoge=4

axiosのparamSerializerに設定する

送信したいパラメータ形式ができたので、axios の paramSerializer にこの関数を設定して、送信時に配列を自動的にフォーマット変換してもらうようにします。
encoder オプションに関数を渡すように少し修正しました。

import qs from 'qs';
import axios from 'axios';
const data = {
  foo: [
    { bar:1, hoge:2 },
    { bar:3, hoge:4 },
  ]
};
function convertParam(str, defaultEncoder, charset, type) {
   console.log(`Type=${type} Str=${str}`);
   if ( type === 'key' ) {
     if (str.match(/¥[bar][/g)) {
       return str.replace(/¥[bar¥]/g, ".bar");
     }
     if (str.match(/¥[hoge][/g)) {
       return str.replace(/¥[hoge¥]/g, ".hoge");
     }
   }
   return str;
}
axios.get(url,
{
  params,
  paramSerializer: (p) => qs.stringify(p, { encoder: convertParam });
});