如何更改嵌套JSON对象中所有属性的值



我正试图从JSON对象中获取一个键/属性,并更改其所有值,无论是嵌套在另一个对象中,还是单独更改。

我有一个区域设置变量

const locale = "en" 

我正试图根据区域设置来更改返回的json对象的值,例如

result.navTitle = result.navTitle[locale]
or
stories.map((story)=> story.navTitle = story.navTitle[locale]);
...etc
result = [
{
"data":{
"en":"English",
"fi":"Finnish"
},
"navTitle":{
"en":"English",
"fi":"Finnish"
},
"stories": [
{
"navTitle":{"en":"English","fi":"Finnish"},
"cards":[
{
"navTitle":{"en":"English","fi":"Finnish"}
},
{
"navTitle":{"en":"English","fi":"Finnish"}
}
]
},
{
"navTitle":{"en":"English","fi":"Finnish"}
}
]
}
]

我已经用重复的.map函数做到了这一点,但它变长了,还有其他选择吗?

您可以创建一个函数,比如getLocaleData(),以获得每个区域设置的相关数据,并采用递归方法选择性地克隆输入数据。

一旦我们到达一个具有"en"、"fi"等属性的子对象,我们将只返回与所需区域设置匹配的属性。

更新:我添加了一个默认值,例如",以在不存在区域设置的情况下返回,并通过示例进行了演示。现在应该将非本地化对象保持原样。

const result = [ { "data":{ "en":"English", "fi":"Finnish" }, features: {}, "navTitle":{ "en":"English", "fi":"Finnish" }, "stories": [ { "navTitle":{"en":"English","fi":"Finnish"}, "cards":[ { "navTitle":{"en":"English","fi":"Finnish"} }, { "navTitle":{"en":"English","fi":"Finnish"} } ] }, { "navTitle":{"en":"English","fi":"Finnish"} } ] } ]
function getLocaleData(obj, locale, defaultValue = '') {
if (!obj) return obj;
// If a property key is 'en', 'fi' etc, return the value.
if (typeof(obj[locale]) === 'string') return obj[locale];

if (Object.keys(obj).length > 0 && Object.keys(obj).every(k => k.length === 2)) { 
return defaultValue;
}
let result = Array.isArray(obj) ? [] : {};
for (let k in obj) {
result[k] = (typeof(obj[k]) === "object") ? getLocaleData(obj[k], locale, defaultValue): obj[k];
}
return result;
}
console.log('nEnglish data:', getLocaleData(result, 'en'));
console.log('nFinnish data:', getLocaleData(result, 'fi'))
// This locale doesn't exist
console.log('nGerman data:', getLocaleData(result, 'de', ''))
.as-console-wrapper { max-height: 100% !important; top: 0; }

您可以使用递归,。

基本上,只需检查对象的数组,如果数组只是映射,如果它是一个对象,你可以使用object.entries/fromEntries来更改,在object.entries的循环中,你可以测试lang,如果条目的值是一个物体,只需将其传递给它自己作为递归位。

以下示例。。

const result = [{"data":{"en":"English","fi":"Finnish"},"navTitle":{"en":"English","fi":"Finnish"},"stories":[{"navTitle":{"en":"English","fi":"Finnish"},"cards":[{"navTitle":{"en":"English","fi":"Finnish"}},{"navTitle":{"en":"English","fi":"Finnish"}}]},{"navTitle":{"en":"English","fi":"Finnish"}}]}];
function langObj(lang, obj) {
if (typeof obj === 'object') {
if (Array.isArray(obj)) {
return obj.map(m => langObj(lang, m));
} else {
return Object.fromEntries(
Object.entries(obj).map(([k,v]) => {
const x = v[lang] || v;
return [k, langObj(lang, x)];
})
);
}
} else {
return obj;
}
}
console.log('English');
console.log(langObj('en', result));
console.log('Finnish');
console.log(langObj('fi', result));

这里有一个使用对象扫描的解决方案,它可能更容易推理。

请注意,此解决方案会修改结果对象,而不会进行复制。如果这是不需要的,它应该在手之前进行克隆(例如使用lodash)。

.as-console-wrapper {max-height: 100% !important; top: 0}
<script type="module">
import objectScan from 'https://cdn.jsdelivr.net/npm/object-scan@18.1.2/lib/index.min.js';
const result = [{ data: { en: 'English', fi: 'Finnish' }, navTitle: { en: 'English', fi: 'Finnish' }, stories: [{ navTitle: { en: 'English', fi: 'Finnish' }, cards: [{ navTitle: { en: 'English', fi: 'Finnish' } }, { navTitle: { en: 'English', fi: 'Finnish' } }] }, { navTitle: { en: 'English', fi: 'Finnish' } }] }];
const rewrite = (data, language) => {
objectScan([`**.${language}`], {
filterFn: ({ gparent, gproperty, value }) => {
if (typeof value === 'string') {
// eslint-disable-next-line no-param-reassign
gparent[gproperty] = value;
}
}
})(data);
};
rewrite(result, 'en');
console.log(result);
// => [ { data: 'English', navTitle: 'English', stories: [ { navTitle: 'English', cards: [ { navTitle: 'English' }, { navTitle: 'English' } ] }, { navTitle: 'English' } ] } ]
</script>

免责声明:我是物体扫描的作者

相关内容

  • 没有找到相关文章

最新更新