Quantcast
Viewing all articles
Browse latest Browse all 8695

TypeScriptでFormDataを良い感じに受け渡ししたい

概要

以前こんな記事を書きました。

JavaScript上でObjectをRailsで取得できる形のFormDataへ変換する
https://qiita.com/dorarep/items/f3aa1463123c1ae75879

今回、似たような形でNode.js上で動くサーバサイド側へ楽にデータを受け渡ししたいので、クライアント側、サーバサイドの変換ロジックをTypeScriptで実装しました。

実装

クライアント側

/**
 * Convert object to FormData which backend can use.
 * This function is useful for uploading files.
 *
 * ex)
 * { id: 1, hero: { id: 1, name: 'NewHero' }, items: [1, 2] }
 * -> FormData with following parameters
 * id: 1
 * hero.id: 1
 * hero.name: NewHero
 * items.: 1
 * items.: 2
 *
 * @param params
 * @return FormData
 */exportconstmakeFormDataFromParams=(params:object):FormData=>{constformData=newFormData();constappendParamsToForm=(variable,prefix='')=>{if(typeofvariable!=='object'||variableinstanceofFile){formData.append(prefix,variable);return;}if(Array.isArray(variable)){variable.forEach(value=>appendParamsToForm(value,`${prefix}.`));return;}Object.keys(variable).forEach(key=>{appendParamsToForm(variable[key]||'',prefix?`${prefix}.${key}`:key);});};appendParamsToForm(params);returnformData;};

サーバサイドはformidableを使用します。

/**
 * ex)
 * id: 1
 * hero.id: 1
 * hero.name: NewHero
 * items.: 1
 * items.: 2
 * -> { id: 1, hero: { id: 1, name: 'NewHero' }, items: [1, 2] }
 *
 * @param req
 * @return object
 */exportconstconvertRequestToObject=async(req)=>{const{IncomingForm}=require('formidable');consthash=awaitnewPromise((resolve,reject)=>{constform=newIncomingForm()form.parse(req,(err,fields,files)=>{if(err)returnreject(err)resolve({...fields,...files})})})returnObject.entries(hash).reduce((current,[path,value])=>mergeDeep(current,buildObject(path,value)),{})}constbuildObject=(path:string,value:any):object=>path.split('.').reverse().reduce((current,path)=>{if(path===''){return[current]}else{return{[path]:current}}},value);constmergeDeep=(target,source)=>{constisObject=(obj)=>obj&&typeofobj==='object';if(!isObject(target)||!isObject(source)){returnsource;}Object.keys(source).forEach(key=>{consttargetValue=target[key];constsourceValue=source[key];if(Array.isArray(targetValue)&&Array.isArray(sourceValue)){target[key]=targetValue.concat(sourceValue);}elseif(isObject(targetValue)&&isObject(sourceValue)){target[key]=mergeDeep(Object.assign({},targetValue),sourceValue);}else{target[key]=sourceValue;}});returntarget;}

ref) mergeDeep
https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6#gistcomment-3120712


Viewing all articles
Browse latest Browse all 8695

Trending Articles