質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

3302閲覧

JSON.parse(JSON.stringify())みたいな形で、文字列からオブジェクトと配列に複合的に変換する方法

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2019/10/03 08:18

以下は文字列なのですが、、、name属性から取ってきています。

aaa[0][header][bbb][0][ccc][0][value]

以下の形式になるように、文字列からオブジェクトに変換するスマートな方法は何かないものでしょうか?
JSON.parse(JSON.stringify())みたいな1行でできる方法はないかを探しています。。。

最初のaaaは別のところでkeyに使うので不要です。(あっても大丈夫です)

let test =[ { header: { bbb: [ { ccc: [ { value: null } ] } ] } } ]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2019/10/03 10:11

「スマートな方法」とありますが、そもそも要件を満たすコードをPOSTMANさん自身の手で作ることが出来たのでしょうか。
guest

回答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
tanishi_a

総合スコア484

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/10/03 14:26

おおお!試していないのでわかりませんが、まさにこういうのを探していました! vueとlaravelを使っているのですが、フォームのname属性はlaravelでmodelをfindしてきたときの構造と同じ作りにしているので、vuexにも同じ構造で持たせたく、e.target.nameで取得してきた値がaaa[0][header][bbb][0][ccc][0][value]なのです。 明日試してみます! ありがとうございます!
退会済みユーザー

退会済みユーザー

2019/10/04 01:17

深い層までは変換してくれないのですね。。。 ``` import * as qs from 'qs'; const a = qs.parse('aaa[0][header][bbb][0][ccc][0][value]'); const a = qs.parse('aaa[0][header][bbb][0][ccc][ddd][0][value]'); console.log(JSON.stringify(a)); console.log(JSON.stringify(b)); {"aaa":[{"header":{"bbb":[{"ccc":{"[0][value]":""}}]}}]} {"aaa":[{"header":{"bbb":[{"ccc":{"[ddd][0][value]":""}}]}}]} ```
tanishi_a

2019/10/04 01:23

qs の npm のドキュメントのページに、オプションで depth が指定できると書いてありますが、どうですかね。
guest

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
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/10/03 13:46

厳しくチェックする方が重要だと押し付けられても、、、。 すみませんが、タイトルは「JSON.parse(JSON.stringify())みたいな形で、文字列からオブジェクトと配列に複合的に変換する方法でコードを短くすることの優位性について各人の意見を伺いたい」ではないので、個人の意見を聞く質問はしておりません。。。
think49

2019/10/04 03:28

親記事に追記しました。 コードを書かずに要件だけ書かれたら、丸投げを疑います。 [質問への追記・修正の依頼] もスルーされています。 回答は、コードで示していましたよ。
guest

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

jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/10/03 10:02

ありがとうございます! いただいたコードの中で、配列をマージしたい場面がありまして、以下のようにすると hello world2の配列しかないようですが何かご存知ないでしょうか? ``` setValueByPath(obj1, 'aaa[0][bbb][ccc][0][ddd][0][value]' , 'hello world1'); setValueByPath(obj2, 'aaa[0][bbb][ccc][0][ddd][1][value]' , 'hello world2'); console.log(Object.assign(obj1, obj2)) ```
jun68ykt

2019/10/03 10:10

コメントありがとうございます。 はい。回答に挙げたコードは、 obj[props[i]] = typeof props[i+1] === 'number' ? [] : {}; となっていて、すでに、obj[props[i]] が存在していても、空オブジェクトか空配列にしてしまうので、 > hello world2の配列しかない ということになります。 一番早い応急処置としては if (!obj[props[i]]) { obj[props[i]] = typeof props[i+1] === 'number' ? [] : {}; } としておけば、以下のようになります。 https://codepen.io/jun68ykt/pen/vYYBLyv?editors=0012 他にも、「こういう場合にこういう結果になるようにしたい」という要件があると思いますので、それらに対応したコードを追加していけばよいかと思います。
jun68ykt

2019/10/03 10:23

ちなみに、 setValueByPath(obj1, 'aaa[0][bbb][ccc][0][ddd][0][value]' , 'hello world1'); setValueByPath(obj2, 'aaa[0][bbb][ccc][0][ddd][1][value]' , 'hello world2'); で作られた、 obj1 と obj2 の深い部分にあるプロパティをマージさせるのは、lodash の _.merge を使えばよいかと思います。 以下、そのサンプルです。 https://codepen.io/jun68ykt/pen/rNNBxpY?editors=0012 参考: https://lodash.com/docs/#merge
退会済みユーザー

退会済みユーザー

2019/10/03 11:52

知識不足&検索能力が足りず申しわけないです。 非常に助かります! ありがとうございます。
jun68ykt

2019/10/03 13:07

どういたしまして。参考になりましたら幸いです。
guest

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
yambejp

総合スコア114769

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2019/10/03 09:20

あ、逆だったすみません
退会済みユーザー

退会済みユーザー

2019/10/03 10:02

回答、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問