

### やりたいこと

###

外部のAPIから受け取ったJSON↓を

[code]

    {
        "message": {
            "listValue": {
                "values": [
                    {
                        "structValue": {
                            "fields": {
                                "replyPayload": {
                                    "structValue": {
                                        "fields": {
                                            "comflow": {
                                                "structValue": {
                                                    "fields": {
                                                        "button": {
                                                            "listValue": {
                                                                "values": [
                                                                    {
                                                                        "structValue": {
                                                                            "fields": {
                                                                                "webview": {
                                                                                    "boolValue": false,
                                                                                    "kind": "boolValue"
                                                                                },
                                                                                "label": {
                                                                                    "structValue": {
                                                                                        "fields": {
                                                                                            "format": {
                                                                                                "boolValue": false,
                                                                                                "kind": "boolValue"
                                                                                            },
                                                                                            "text": {
                                                                                                "stringValue": "端末選択に戻る",
                                                                                                "kind": "stringValue"
                                                                                            }
                                                                                        }
                                                                                    },
                                                                                    "kind": "structValue"
                                                                                },
                                                                                "event": {
                                                                                    "structValue": {
                                                                                        "fields": {
                                                                                            "name": {
                                                                                                "stringValue": "eventName1",
                                                                                                "kind": "stringValue"
                                                                                            }
                                                                                        }
                                                                                    },
                                                                                    "kind": "structValue"
                                                                                }
                                                                            }
                                                                        },
                                                                        "kind": "structValue"
                                                                    },
                                                                    {
                                                                        "structValue": {
                                                                            "fields": {
                                                                                "event": {
                                                                                    "structValue": {
                                                                                        "fields": {
                                                                                            "name": {
                                                                                                "stringValue": "eventName2",
                                                                                                "kind": "stringValue"
                                                                                            }
                                                                                        }
                                                                                    },
                                                                                    "kind": "structValue"
                                                                                },
                                                                                "webview": {
                                                                                    "boolValue": false,
                                                                                    "kind": "boolValue"
                                                                                },
                                                                                "label": {
                                                                                    "structValue": {
                                                                                        "fields": {
                                                                                            "format": {
                                                                                                "boolValue": false,
                                                                                                "kind": "boolValue"
                                                                                            },
                                                                                            "text": {
                                                                                                "stringValue": "メニューに戻る",
                                                                                                "kind": "stringValue"
                                                                                            }
                                                                                        }
                                                                                    },
                                                                                    "kind": "structValue"
                                                                                }
                                                                            }
                                                                        },
                                                                        "kind": "structValue"
                                                                    }
                                                                ]
                                                            },
                                                            "kind": "listValue"
                                                        }
                                                    }
                                                },
                                                "kind": "structValue"
                                            },
                                            "title": {
                                                "structValue": {
                                                    "fields": {
                                                        "format": {
                                                            "boolValue": false,
                                                            "kind": "boolValue"
                                                        },
                                                        "text": {
                                                            "stringValue": "メニューまたは機種選択に戻る場合は、下のボタ ンを押してください。",
                                                            "kind": "stringValue"
                                                        }
                                                    }
                                                },
                                                "kind": "structValue"
                                            }
                                        }
                                    },
                                    "kind": "structValue"
                                }
                            }
                        },
                        "kind": "structValue"
                    }
                ]
            },
            "kind": "listValue"
        }
    }
    
[/code]

このような形↓にしたいのですがうまくいきません。

[code]

    {
      "message": [
        {
          "replyPayload": {
            "title": {
              "format": false,
              "text": "選択"
            },
            "comflow": {
              "button": [
                {
                  "label": {
                    "format": false,
                    "text": "トップに戻る"
                  },
                  "event": {
                    "name": "eventName1"
                  }
                },
                {
                  "webview": false,
                  "label": {
                    "format": false,
                    "text": "前に戻る"
                  },
                  "event": {
                    "name": "eventName2"
                  }
                }
              ]
            }
          }
        }
      ]
    }
    
[/code]

### 試したコード・結果

試したコード↓

[code]

    let message = data.payload.fields.message;
    const analysisArr = [];
    analysis(message);
    let payload = {message : analysisArr};
    console.log(payload);
    
    function analysis(obj) {
        try {
            console.log('obj => ' + JSON.stringify(obj));
            let box = {};
            if (obj.structValue) {
                box = obj.structValue.fields;
                Object.keys(box).forEach(function(key) {
                    analysisArr.push({[key] : {}});
                    console.log('analysisArr => ' + JSON.stringify(analysisArr));
                    analysis(box[key], key);
                });
            } else if (obj.listValue) {
                analysisArr.push([]);
                console.log('analysisArr => ' + JSON.stringify(analysisArr));
                box = obj.listValue.values;
                box.forEach(function(val, key) {
                    analysis(val);
                });
            } else if (obj.stringValue) {
                const l = analysisArr.length;
                const parent = analysisArr[l-1];
                const parentKey = Object.keys(parent);
                parent[parentKey[0]] = obj.stringValue;
                console.log('analysisArr => ' + JSON.stringify(analysisArr));
                for (let i = l-2; i > -1; i--) {
                    if (Object.prototype.toString.call(analysisArr[i]) === '[object Object]') { // 自分
                        const cpm = analysisArr[i];
                        console.log('\ncpm => ' + JSON.stringify(cpm));
                        const keyArr = Object.keys(cpm);
                        const child = analysisArr[i+1];
                        if (Object.prototype.toString.call(cpm[keyArr[0]]) === '[object Object]' && !Object.keys(cpm[keyArr[0]]).length) { // 自分のプロパティ
                            if (Object.prototype.toString.call(child) === '[object Array]') { // child
                                cpm[keyArr[0]] = child;
                            } else {
                                const childKey = Object.keys(child);
                                const type = Object.prototype.toString.call(child[childKey[0]]);
                                console.log('type => ' + type);
                                if (type === '[object Object]' || type === '[object String]' || type === '[object Number]' || type === '[object Boolean]') { // childのプロパティ
                                    cpm[keyArr[0]] = {[childKey[0]] : child[childKey[0]]};
                                } else if (Object.prototype.toString.call(child[childKey[0]]) === '[object Array]') {
                                    cpm[keyArr[0]] = child;
                                }
                            }
                        } else if (Object.prototype.toString.call(cpm[keyArr[0]]) === '[object Object]' && Object.keys(cpm[keyArr[0]]).length) {
                            if (Object.prototype.toString.call(child) === '[object Array]') { // child
                                cpm[keyArr[0]] = child;
                                //nestCount++;
                            } else {
                                const childKey = Object.keys(child);
                                cpm[childKey[0]] = child[childKey[0]];
                                //nestCount++;
                            }
                        } else if (Object.prototype.toString.call(cpm[keyArr[0]]) === '[object Array]') {
                            cpm[keyArr[0]].push(child);
                        }
                        analysisArr.pop();
                        console.log('analysisArr => ' + JSON.stringify(analysisArr));
                    } else if (Object.prototype.toString.call(analysisArr[i]) === '[object Array]') {
                        const child = analysisArr.pop();
                        analysisArr[i].push(child);
                        console.log('\nis Array');
                        console.log('analysisArr => ' + JSON.stringify(analysisArr));
                    }
                }
            }
            return null;
    
        } catch(error) {
            console.log(error);
            return null;
        }
    }
    
[/code]

結果

[code]

      {
        "message": [
            [
                {
                    "replyPayload": {
                        "title": {
                            "text": "選択"
                        }
                    }
                },
                {
                    "format": false
                },
                {
                    "comflow": {
                        "button": [
                            {
                                "label": {
                                    "text": "トップに戻る"
                                }
                            }
                        ]
                    }
                },
                {
                    "format": false
                },
                {
                    "event": {
                        "name": "eventName1"
                    }
                },
                {
                    "event": {
                        "name": "eventName2"
                    }
                },
                {
                    "webview": false
                },
                {
                    "label": {
                        "format": false
                    }
                },
                {
                    "text": "前に戻る"
                }
            ]
        ]
    }
    
[/code]

###

配列のときは **listValue:{values:[]}** ,  
オブジェクトのときは **structValue:{fields:{}}** ,  
文字列のときは **stringValue: "文字列"**,  
論理型のときは **boolValue:論理値** ,  
になっているのはわかったのですがどうすれば下の形にできるかわかりません。  
やり方がわかる方いましたら教えてください。


CC BY-SA 4.0
2019-07-10T09:03:55.737
56545
2019-07-10T16:30:12.657
2020-06-17T08:14:45.997
-1
35048
question
javascript node.js json
JSONデータを成形して出力する


提示の質問の目的を達成できるコードを試しにTypeScriptで書き直してみたところ(型定義などは雑ですが)メイン部分は20行弱で達成することができました。以下に示します。

[code]

    type IListValue = {
        kind: "listValue"
        listValue: {
            values: IValue[]
        }
    }
    
    type IStructValue = {
        kind: "structValue"
        structValue: {
            fields: {
                [key: string]: IValue
            }
        }
    }
    
    type IBoolValue = {
        kind: "boolValue"
        boolValue: boolean
    }
    
    
    type IStringValue = {
        kind: "stringValue"
        stringValue: string
    }
    
    type IValue = IListValue | IStructValue | IBoolValue | IStringValue
    type IMessage = {
        message: IValue
    }
    
    const message: IMessage = {
      ...
    }
    
    const parse = (value: IValue) : any  => {
        switch(value.kind) {
            case "boolValue":
                return value.boolValue
            case "stringValue":
                return value.stringValue
            case "listValue":
                return value.listValue.values.map(parse)
            case "structValue":
                const res: {[key: string]: any} = {}
                for(const key of Object.keys(value.structValue.fields)) {
                    res[key] = value.structValue.fields[key]
                }
                return res
        }
    }
    
    const result = {
        message: parse(message.message)
    }
    console.log(result)
    
[/code]

マルチポスト先でも指摘されているよう「どの部分がうまくいかないか」をもうすこし具体的にしていただかないとあまりお手伝いできませんが、入れ子構造のものを扱うのであれば下手にループで無理しようとせずに再帰でやるのが得策な気はします……とかいてから質問文のコード読みなおしたら一応再帰らしきものは使われてるようでしたね。ただ再帰の使い方がよくないようですが……。


CC BY-SA 4.0
2019-07-10T16:30:12.657
56550
2019-07-10T16:30:12.657
2376
56545
answer