Estoy tratando de obtener una clave/propiedad de un objeto JSON y cambiar todos sus valores, ya sea que esté anidado dentro de otro objeto o por sí mismo.
Tengo una variable local
const locale = "en"y estoy tratando de cambiar el valor del objeto json devuelto según la configuración regional, como
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"} } ] } ]Me las he arreglado para hacer esto con funciones .map repetitivas pero se hace largo, ¿hay alguna otra alternativa para hacer esto?
Puedes usar la recursividad.
Básicamente, solo verifique si la matriz del objeto, si la matriz simplemente mapea, si es un objeto, puede usar Object.entries / fromEntries para cambiar, dentro del bucle de Object.entries, luego puede probar el idioma, si los valores de las entradas son un objeto, simplemente páselo a sí mismo para el bit de recursión.
Ejemplo a continuación..
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));Puede crear una función, digamos getLocaleData() para obtener los datos relevantes para cada configuración regional, adoptando un enfoque recursivo para clonar selectivamente los datos de entrada.
Una vez que alcancemos un objeto secundario con propiedades como 'en', 'fi', etc., devolveremos solo la propiedad que coincida con la configuración regional deseada.
Actualización: he agregado un valor predeterminado, por ejemplo, '' para regresar si la configuración regional no está presente y se demuestra con un ejemplo. Esto ahora debería dejar los objetos no localizados como están.
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; }Aquí hay una solución que usa el escaneo de objetos que podría ser un poco más fácil de razonar.
Tenga en cuenta que esta solución modifica el objeto de resultado y no hace una copia. Si esto no se desea, se debe clonar de antemano (usando, por ejemplo, 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>Descargo de responsabilidad: soy el autor de object-scan