多次元オブジェクトであること
再帰関数を使って掘り進める事になります。
フィボナッチ数列にしか使えないテクニックではなく、
意外とこういう再帰的に掘り進めたいケースで使われます。
因みにJavaScriptに於ける再帰関数は無限に掘り進めるわけではなく、
ChromeやFirefox等に積んでいるJavaScriptエンジンに左右されます。
だいたい1000階層くらいになるとエラーで死ぬので、それより浅いと想定されるケースでしか使えません。
今回のケースではそんなアホみたいな巨大なJSONは帰ってこないと思うので
再帰関数を利用するのが最善でしょう。
オブジェクトを配列のように扱って、そのあとオブジェクトに戻すという方法が思いつきません。
Object.fromEntriesと
Object.entries
これで双方向に変換出来ます。
それではやっていきましょう。
とりま質問文の値をres
変数にでも保管しましょうか。
js
1const res = {
2 "products": {
3 "edges": [
4 {
5 "node": {
6 "description": "Sleek and black",
7 "featuredImage": {
8 "id": "gid://shopify/ProductImage/15464783282345",
9 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
10 },
11 "handle": "skirt",
12 "id": "gid://shopify/Product/4773734482089",
13 "images": {
14 "edges": [
15 {
16 "node": {
17 "id": "gid://shopify/ProductImage/15464783282345",
18 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
19 }
20 },
21 {
22 "node": {
23 "id": "gid://shopify/ProductImage/26072838406313",
24 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb7.jpg?v=1612636091"
25 }
26 },
27 {
28 "node": {
29 "id": "gid://shopify/ProductImage/26072838373545",
30 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb6.jpg?v=1612636091"
31 }
32 }
33 ]
34 }
35 }
36 }
37 ]
38 }
39}
ドキュメントによると
エッジはノードとカーソルを持ち、カーソルはページネーション用なので
画面表示には使わないので捨てるという感じでしょうかね。
つまりedgeキーを見つけたら配列を展開して
nodeを取り出してそれに置きかえるという事をやりましょうか。
js
1const removeEdge = obj => {
2 if (typeof obj != 'object') return obj;
3 return Object.fromEntries(
4 Object.entries(obj).map(([key, val]) => {
5 if (!Array.isArray(val.edges)) return [key, val];
6 return [
7 key,
8 // edgesが配列であるのでmapで変換して
9 // 再度removeEdgeで精査している
10 val.edges.map(it => removeEdge(it?.node))
11 ];
12 })
13 );
14};
実際コードにしたら結構色々テクニックを使ってますね。
JavaScriptはnullやundefined値にプロパティを所持出来ません。
これらの値にアクセスを試みただけでJavaScriptがエラーで落ちるので、
edge[n].node
を決め打ちで参照する時に利用しています。
js
1JSON.stringify(removeEdge(res), null, 2);
JSON
1{
2 "products": [
3 {
4 "description": "Sleek and black",
5 "featuredImage": {
6 "id": "gid://shopify/ProductImage/15464783282345",
7 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
8 },
9 "handle": "skirt",
10 "id": "gid://shopify/Product/4773734482089",
11 "images": [
12 {
13 "id": "gid://shopify/ProductImage/15464783282345",
14 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb20.jpg?v=1602116082"
15 },
16 {
17 "id": "gid://shopify/ProductImage/26072838406313",
18 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb7.jpg?v=1612636091"
19 },
20 {
21 "id": "gid://shopify/ProductImage/26072838373545",
22 "originalSrc": "https://cdn.shopify.com/s/files/1/0268/1005/6873/products/bb6.jpg?v=1612636091"
23 }
24 ]
25 }
26 ]
27}
ただまぁ、エラー処理周りとか適当ですし、
そもそも要件を満たしているかは知らないので責任は持てません。
質問文を読んだ上で、「こういうアプローチで何とかなりそう」程度の指針を示す事は出来たかなと思います。
ここから更に改良して相応しいエラー処理等を付け足してみてください。