通过数组内对象的属性转换JSON

时间:2018-10-28 15:49:40

标签: javascript json

我有一个对象或对象数组,道具包含字符串,数组和其他对象。

我想将包含带有道具language的对象的嵌套数组转换为以language为键且对象本身为prop的对象。

给出对象:

{
    "id": 1,
    "title": "First",
    "ProjectsTranslations": [ // This one
        {
            "id": 1,
            "language": "en"
        },
        {
            "id": 2,
            "language": "de"
        }
    ],
    "someObject": {
        "someProp1": "Some string1",
        "someProp2": "Some string2"
    },
    "someArray": [
        {
            "someProp1": "Some string1"
        },
        {
            "someProp1": "Some string1"
        }
    ]
}

我正在尝试将其转换为:

{
    "id": 1,
    "title": "First",
    "ProjectsTranslations": {
        // This one
        "en": {
            "id": 1,
            "language": "en"
        },
        "de": {
            "id": 2,
            "language": "de"
        }
    },
    "someObject": {
        "someProp1": "Some string1",
        "someProp2": "Some string2"
    },
    "someArray": [
        {
            "someProp1": "Some string1"
        },
        {
            "someProp1": "Some string1"
        }
    ]
}

给出数组:

[
    {
        "id": 1,
        "title": "First",
        "ProjectsTranslations": [
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ]
    },
    {
        "id": 1,
        "title": "Second",
        "ProjectsTranslations": [
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ]
    }
]

进入:

[
    {
        "id": 1,
        "title": "First",
        "ProjectsTranslations": {
            "en": {
                "id": 1,
                "language": "en"
            },
            "de": {
                "id": 1,
                "language": "de"
            }
        }
    },
    {
        "id": 2,
        "title": "Second",
        "ProjectsTranslations": {
            "en": {
                "id": 1,
                "language": "en"
            },
            "de": {
                "id": 1,
                "language": "de"
            }
        }
    },
]

我一直在试图找到一种方法,但是似乎很困难。有什么建议吗?我正在尝试不使用Lodash或Underscore。


编辑

我找到了一种方法,但是这并不是我想要的。我递归检查所有对象,如果其中一个是数组,并且其名称包含字符串translations,则从那里开始操作。但这需要一个命名约定-所有可翻译模型的名称都应带有Translations-我不喜欢。这是功能,但是如果有解决方案,可以检查lang值,那么就好。

export const transformTranslatedData = function(data) {
    var clonedData = JSON.parse(JSON.stringify(data));

    const transform = function(data) {
        for (const prop in data) {
            if (data[prop] instanceof Array && prop.includes('Translations')) {
                data[prop] = data[prop].reduce(function(prev, current, index) {
                    prev[current.language] = current;

                    return prev;
                }, {});
            }
            if (data[prop] instanceof Object && !(data[prop] instanceof Array)) {
                transformTranslatedData(data[prop]);
            }
        }

        return data;
    };
    // Check if its an Array; if it is, iterate over it and push transformed objects into new array.
    if (clonedData instanceof Array) {
        var newData = [];
        clonedData.map((item) => {

            newData.push(transform(item));
        });
    } else if (clonedData instanceof Object && !(clonedData instanceof Array)) {
        var newData = {};

        newData = transform(clonedData);
    }

    return newData;
};

编辑2

我设法检查数组中对象的属性。如此简单:

data[prop] instanceof Array && data[prop].length > 0 && data[prop][0].hasOwnProperty('language')

最终功能是:

export const transformTranslatedData = function(data) {
    var clonedData = JSON.parse(JSON.stringify(data));

    const transform = function(data) {
        for (const prop in data) {
            if (data[prop] instanceof Array && data[prop].length > 0 && data[prop][0].hasOwnProperty('language')) {
                data[prop] = data[prop].reduce(function(prev, current, index) {
                    prev[current.language] = current;

                    return prev;
                }, {});
            }
            if (data[prop] instanceof Object && !(data[prop] instanceof Array)) {
                transformTranslatedData(data[prop]);
            }
        }

        return data;
    };
    if (clonedData instanceof Array) {
        var newData = [];
        clonedData.map((item) => {
            newData.push(transform(item));
        });
    } else if (clonedData instanceof Object && !(clonedData instanceof Array)) {
        var newData = {};

        newData = transform(clonedData);
    }

    return newData;
};

但是有点脏……

3 个答案:

答案 0 :(得分:0)

您可以使用数组中的reduce函数。

reduce遍历数组,并将结果聚合到您的第一个参数中(在我们的例子中为agg)。

最后,const result = { ...obj, ProjectsTranslations: newProjectTranslation }用我创建的新内容覆盖了ProjectsTranslations

来自MDN:

  

reduce()方法在数组的每个成员上执行reducer函数(由您提供),从而产生单个输出值。

const obj = {
        "id": 1,
        "title": "First",
        "ProjectsTranslations": [ // This one
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ],
        "someObject": {
            "someProp1": "Some string1",
            "someProp2": "Some string2"
        },
        "someArray": [
            {
                "someProp1": "Some string1"
            },
            {
                "someProp1": "Some string1"
            }
        ]
    }

    getModifiedObject = (someObject, key) => {
      let ProjectsTranslations = someObject.ProjectsTranslations

      const newProjectTranslation = ProjectsTranslations.reduce((agg, item) => {
        const lang = item[key]
        agg[lang] = item
        return agg
      }, {})

      return { ...obj, ProjectsTranslations: newProjectTranslation }
    }



    console.log(getModifiedObject(obj, 'language'))

答案 1 :(得分:0)

尝试一下,可能会对您有所帮助

    var obj1= {
        "id": 1,
        "title": "First",
        "ProjectsTranslations": [ // This one
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ],
        "someObject": {
            "someProp1": "Some string1",
            "someProp2": "Some string2"
        },
        "someArray": [
            {
                "someProp1": "Some string1"
            },
            {
                "someProp1": "Some string1"
            }
        ]
    };
transformObject(obj1,"ProjectsTranslations");

function transformObject(obj1,arrayKey){
    var ProjectsTranslationsObj ={};


    for (var i=0;i< obj1[arrayKey].length;i++){
       var key =obj1[arrayKey][i].language;
       ProjectsTranslationsObj[key] = obj1[arrayKey][i];
    };


    obj1[arrayKey] = ProjectsTranslationsObj;
}

答案 2 :(得分:0)

创建了一个函数changeProjectsTranslations,用于将数组更改为对象。

function changeProjectsTranslations(obj) {
    /*
        let obj = {
            "id": 1,
            "title": "First",
            "ProjectsTranslations": [
                {
                    "id": 1,
                    "language": "en"
                },
                {
                    "id": 2,
                    "language": "de"
                }
            ]
        }
    */

    let oldLanguage = obj.ProjectsTranslations,
        newLanguage = {};

    for(let o of oldLanguage) {
        newLanguage[o.language] = o;
    }

    obj.ProjectsTranslations = newLanguage;

    return obj;

}

let array = [
    {
        "id": 1,
        "title": "First",
        "ProjectsTranslations": [
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ]
    },
    {
        "id": 1,
        "title": "Second",
        "ProjectsTranslations": [
            {
                "id": 1,
                "language": "en"
            },
            {
                "id": 2,
                "language": "de"
            }
        ]
    }
];

for (let i = 0; i < array.length; i++) {
    array[i] = changeProjectsTranslations(array[i]);
}

console.log(array);