以下は文字列なのですが、、、name属性から取ってきています。
aaa[0][header][bbb][0][ccc][0][value]
以下の形式になるように、文字列からオブジェクトに変換するスマートな方法は何かないものでしょうか?
JSON.parse(JSON.stringify())
みたいな1行でできる方法はないかを探しています。。。
最初のaaaは別のところでkeyに使うので不要です。(あっても大丈夫です)
let test =[ { header: { bbb: [ { ccc: [ { value: null } ] } ] } } ]
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
POST のパラメータですかね? qs
というライブラリが、まさにその仕事をしている気がします。
TypeScript
1import * as qs from 'qs'; 2 3const a = qs.parse('aaa[0][header][bbb][0][ccc][0][value]'); 4console.log(JSON.stringify(a));
結果
txt
1{"aaa":[{"header":{"bbb":[{"ccc":{"[0][value]":""}}]}}]}
投稿2019/10/03 14:16
編集2019/10/03 14:50総合スコア484
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/10/03 14:26
退会済みユーザー
2019/10/04 01:17
2019/10/04 01:23
退会済みユーザー
2019/10/04 01:37
0
要件不明瞭
以下の形式になるように、文字列からオブジェクトに変換するスマートな方法は何かないものでしょうか?
漠然と「スマート」と書かれても回答者には伝わりませんので、要件は「具体的」に書いて下さい。
JSON.parse(JSON.stringify())みたいな1行でできる方法はないかを探しています。。。
1行で書きました。
厳密性
コードを短くする事よりも、文法を厳密にして、厳しくチェックする方が重要だと思います。
厳しくチェックする方が重要だと押し付けられても、、、。
厳密性を問うのは、要件が厳密でないコードは、予期せぬ不具合を仕込むからです。
JavaScript
1/** 2 * エラーを返すべき文字列 3 */ 4'abc'; 5'abc[0]['; 6'abc[0]xyz[a]'; 7'abc['; 8'abc[]'; 9 10/** 11 * 正しくパースされるべき文字列 12 */ 13'abc[x[yz]'; // {'x[yz':null}
先に私が提案したコードは、この仕様に準じています。
例えば、ベストアンサーに選ばれたjun68yktさんのコードは、独特の動きをします。
JavaScript
1setValueByPath(obj, 'aaa[0]bbb[header]ccc[bbb]' , 'hello world');
再帰処理
ご指定の文法は、複数のトークンに分けて、複数回マッチさせる必要があるので、再帰処理が必要になります。
A. String.prototype.replace
にgフラグ付正規表現、コールバック関数を指定
B. RegExp.prototype.exec
にgフラグ付正規表現を指定し、while
ループ
今回、必要な返り値は文字列ではないので、B. を採用しました。
Re: POSTMAN さん
投稿2019/10/03 13:05
編集2019/10/04 03:24総合スコア18189
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/10/03 13:46
2019/10/04 03:28
0
ベストアンサー
こんにちは
細部(与えられる文字列のどこかに不正な箇所があった場合の対応など)は詰めていませんが、おそらくこんなようなコードを書くことになるのではと思います。
javascript
1const setValueByPath = (obj, path, value) => { 2 const props = path.split(/[[]]/).filter(str => str).map(str => /^[0-9]+$/.test(str) ? +str : str); 3 4 for (let i=0; i < props.length - 1; i ++ ) { 5 obj[props[i]] = typeof props[i+1] === 'number' ? [] : {}; 6 obj = obj[props[i]]; 7 } 8 9 obj[props[props.length - 1]] = value; 10} 11 12const obj = {}; 13 14setValueByPath(obj, 'aaa[0][header][bbb][0][ccc][0][value]' , 'hello world');
以下は、上記の動作確認用に CodePen に上げたものです。
ちなみに、stackoverflow に類似の投稿がありました。
以上、参考になれば幸いです。
投稿2019/10/03 09:19
総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/10/03 10:02
2019/10/03 10:10
2019/10/03 10:23
退会済みユーザー
2019/10/03 11:52
2019/10/03 13:07
0
スマートな方法は何かない
おそらくありません。冗長に再帰処理をかけるとよいのでは?
const test =[ { "header":{ "bbb": [ { "ccc": [ { "value": null } ] } ] } } ]; const get_val_recursive=obj=>{ var ret=""; if(obj && (k=Object.keys(obj)).length>0){ const enc=isNaN(k[0])?"\"":""; ret+="["+enc+k[0]+enc+"]"; ret=ret+ get_val_recursive(Object.values(obj)[0]); } return ret; } console.log(get_val_recursive(test));
投稿2019/10/03 09:10
編集2019/10/03 09:11総合スコア116690
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。