I have a json response that i'm getting from an api and mongoDB as following:
I'm passing query Param in the request which I also have access to it in nestjs app.service.ts
query param ?locale
can be either en
, es
, or de
default one being en
if no ?locale
is passed in the URL
[
{
"name": {
"en": "PLA",
"de": "PLA",
"es": "PLA"
},
"density": 5.17,
"id": "32ccfa8d-8db6-41f6-83fa-7726851bffd4",
"image": "https://test.image/pla",
"description": {
"en": "PLA English description",
"de": "PLA deutsche Beschreibung",
"es": "PLA descripción en español"
},
"finishes": [
{
"name": {
"en": "Standard",
"de": "Standard",
"es": "Estándar"
},
"materialId": "32ccfa8d-8db6-41f6-83fa-7726851bffd4",
"colorIds": [
"9704a8b0-ae94-4945-94ef-8445b387d48d",
"1ba6c1ae-8c41-47f3-b925-11316afd1ddd",
"d648994f-b1fa-4982-969e-eee2f7a68c77",
"d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e",
"e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"
],
"id": "8f529b1f-18a8-408b-a88c-b9056ef6e50e",
"image": "https://test.image/pla_standard",
"description": {
"en": "PLA Standard English description",
"de": "PLA Standard deutsche Beschreibung",
"es": "PLA estándar descripción en español"
},
"colors": [
{
"_id": "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e",
"name": {
"en": "PLA",
"de": "PLA",
"es": "PLA"
},
"hexCode": "#00CC33",
"id": "32ccfa8d-8db6-41f6-83fa-7726851bffd4",
"image": "https://test.image/pla",
"description": {
"en": "PLA English description",
"de": "PLA deutsche Beschreibung",
"es": "PLA descripción en español"
}
},
{
"_id": "1ba6c1ae-8c41-47f3-b925-11316afd1ddd",
"name": {
"en": "316L Stainless Steel",
"de": "316L Rostfreier Stahl",
"es": "316L Acero Inoxidable"
},
"hexCode": "#000000",
"id": "c7bc7177-8137-4552-a218-0aa4d2491373",
"image": "https://test.image/316L",
"description": {
"en": "316L English description",
"de": "316L deutsche Beschreibung",
"es": "316L descripción en español"
}
},
{
"_id": "d648994f-b1fa-4982-969e-eee2f7a68c77",
"name": {
"en": "MJF Nylon PA12",
"de": "MJF Nylon PA12",
"es": "MJF Nylon PA12"
},
"hexCode": "#FF465B",
"id": "5857ed97-bc6f-4e30-84c7-864d63fa2ab5",
"image": "https://test.image/mjf_nylon",
"description": {
"en": "MJF Nylon PA12 English description",
"de": "MJF Nylon PA12 deutsche Beschreibung",
"es": "MJF Nylon PA12 descripción en español"
}
}
]
},
{
"name": {
"en": "Polished",
"de": "Poliert",
"es": "Pulido"
},
"materialId": "32ccfa8d-8db6-41f6-83fa-7726851bffd4",
"colorIds": [
"9704a8b0-ae94-4945-94ef-8445b387d48d",
"1ba6c1ae-8c41-47f3-b925-11316afd1ddd",
"d648994f-b1fa-4982-969e-eee2f7a68c77",
"d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e",
"e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"
],
"id": "9704a8b0-ae94-4945-94ef-8445b387d48d",
"image": "https://test.image/mjf_nylon_polished",
"description": {
"en": "MJF Nylon PA12 polished English description",
"de": "MJF Nylon PA12 poliert deutsche Beschreibung",
"es": "MJF Nylon PA12 pulido descripción en español"
},
"colors": [
{
"_id": "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e",
"name": {
"en": "PLA",
"de": "PLA",
"es": "PLA"
},
"hexCode": "#00CC33",
"id": "32ccfa8d-8db6-41f6-83fa-7726851bffd4",
"image": "https://test.image/pla",
"description": {
"en": "PLA English description",
"de": "PLA deutsche Beschreibung",
"es": "PLA descripción en español"
}
},
{
"_id": "1ba6c1ae-8c41-47f3-b925-11316afd1ddd",
"name": {
"en": "316L Stainless Steel",
"de": "316L Rostfreier Stahl",
"es": "316L Acero Inoxidable"
},
"hexCode": "#000000",
"id": "c7bc7177-8137-4552-a218-0aa4d2491373",
"image": "https://test.image/316L",
"description": {
"en": "316L English description",
"de": "316L deutsche Beschreibung",
"es": "316L descripción en español"
}
},
{
"_id": "d648994f-b1fa-4982-969e-eee2f7a68c77",
"name": {
"en": "MJF Nylon PA12",
"de": "MJF Nylon PA12",
"es": "MJF Nylon PA12"
},
"hexCode": "#FF465B",
"id": "5857ed97-bc6f-4e30-84c7-864d63fa2ab5",
"image": "https://test.image/mjf_nylon",
"description": {
"en": "MJF Nylon PA12 English description",
"de": "MJF Nylon PA12 deutsche Beschreibung",
"es": "MJF Nylon PA12 descripción en español"
}
}
]
}
]
}...]
what I would like to do is get the following parsed json ideally by ramdajs but vanillaJS should also work:
{
"materials": [
{
"id": "8b4c3e04-beb1-40b4-885a-bba33300d14e",
"name": "PLA",
"image": "https://test.image/pla",
"density": 1.2,
"finishes": [
{
"id": "04eb376d-0790-4c41-a45f-164fb0414892",
"name": "Standard",
"image": "https://image/pla_standard",
"description": "PLA description",
"colors": [{
"id": "78bd5280-9199-414c-b0fd-df01f18807e1",
"name": "White",
"hexCode": "#FFFFFF"
},
{
"id": "78bd5280-9199-414c-b0fd-df01f18807e1",
"name": "Black",
"hexCode": "#000000"
}]
}
]
}
]
}
I am parsing the current response like this:
const catalog = (parsedMaterials) => (parsedFinishes) => (parsedColors) =>
parsedMaterials.map((material) => ({
...material,
finishes: parsedFinishes
.filter((finish) => {
return finish.materialId == material.id;
})
.map((finish) => ({
...finish,
colors: parsedColors.filter((color) => {
return finish.colorIds.includes(color._id);
}),
})),
}));
Update:
a comment asked how I'm getting the above mapped through variables:
I'm fetching responses from both a mongoDB source and a Rest-api, i'm chaining the promises and then storing the results in the above mentioned variables after merging them.
const getMaterials = () =>
Promise.all([
getMongoDBMaterials(this.materialsRepository),
getCMSMaterials(),
]).then(R.apply(R.zipWith(R.mergeRight)));
const getFinishes = () =>
Promise.all([
getMongoDBFinishes(this.finishesRepository),
getCMSFinishes(),
]).then(R.apply(R.zipWith(R.mergeRight)));
const getColors = () =>
Promise.all([
getMongoDBColors(this.colorsRepository),
getCMSColors(),
]).then(R.apply(R.zipWith(R.mergeRight)));
const parsedMaterials = await getMaterials()
.then((data) => {
return data;
})
.catch((err) => console.log(`Error: ${err}`));
const parsedColors = await getColors()
.then((data) => {
return data;
})
.catch((err) => console.log(`Error: ${err}`));
const parsedFinishes = await getFinishes()
.then((data) => {
return data;
})
.catch((err) => console.log(`Error: ${err}`));
Thank you
CodePudding user response:
Here is a suggestion for the locale handling, based on the input and output structure you suggest. It does not try to do anything with the rest of the restructuring.
It is based on a somewhat flexible function that looks deeply for properties (and sub-properties, and sub-sub-properties, etc.) with certain keys, and replaces them by looking up the value for a given fixed key (here your language parameter.)
It might look like this:
const chooseNestedProps = (props) => (val) => (obj) =>
Array .isArray (obj)
? obj .map (chooseNestedProps (props) (val))
: Object (obj) === obj
? Object .fromEntries (Object .entries (obj) .map (([k, v]) =>
[k, props .includes (k) ? v [val] : chooseNestedProps (props) (val) (v)]
))
: obj
const input = [{name: {en: "PLA", de: "PLA", es: "PLA"}, density: 5.17, id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}, finishes: [{name: {en: "Standard", de: "Standard", es: "Estándar"}, materialId: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", colorIds: ["9704a8b0-ae94-4945-94ef-8445b387d48d", "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", "d648994f-b1fa-4982-969e-eee2f7a68c77", "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", "e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"], id: "8f529b1f-18a8-408b-a88c-b9056ef6e50e", image: "https: //test.image/pla_standard", description: {en: "PLA Standard English description", de: "PLA Standard deutsche Beschreibung", es: "PLA estándar descripción en español"}, colors: [{_id: "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", name: {en: "PLA", de: "PLA", es: "PLA"}, hexCode: "#00CC33", id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}}, {_id: "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", name: {en: "316L Stainless Steel", de: "316L Rostfreier Stahl", es: "316L Acero Inoxidable"}, hexCode: "#000000", id: "c7bc7177-8137-4552-a218-0aa4d2491373", image: "https: //test.image/316L", description: {en: "316L English description", de: "316L deutsche Beschreibung", es: "316L descripción en español"}}, {_id: "d648994f-b1fa-4982-969e-eee2f7a68c77", name: {en: "MJF Nylon PA12", de: "MJF Nylon PA12", es: "MJF Nylon PA12"}, hexCode: "#FF465B", id: "5857ed97-bc6f-4e30-84c7-864d63fa2ab5", image: "https: //test.image/mjf_nylon", description: {en: "MJF Nylon PA12 English description", de: "MJF Nylon PA12 deutsche Beschreibung", es: "MJF Nylon PA12 descripción en español"}}]}, {name: {en: "Polished", de: "Poliert", es: "Pulido"}, materialId: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", colorIds: ["9704a8b0-ae94-4945-94ef-8445b387d48d", "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", "d648994f-b1fa-4982-969e-eee2f7a68c77", "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", "e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"], id: "9704a8b0-ae94-4945-94ef-8445b387d48d", image: "https: //test.image/mjf_nylon_polished", description: {en: "MJF Nylon PA12 polished English description", de: "MJF Nylon PA12 poliert deutsche Beschreibung", es: "MJF Nylon PA12 pulido descripción en español"}, colors: [{_id: "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", name: {en: "PLA", de: "PLA", es: "PLA"}, hexCode: "#00CC33", id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}}, {_id: "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", name: {en: "316L Stainless Steel", de: "316L Rostfreier Stahl", es: "316L Acero Inoxidable"}, hexCode: "#000000", id: "c7bc7177-8137-4552-a218-0aa4d2491373", image: "https: //test.image/316L", description: {en: "316L English description", de: "316L deutsche Beschreibung", es: "316L descripción en español"}}, {_id: "d648994f-b1fa-4982-969e-eee2f7a68c77", name: {en: "MJF Nylon PA12", de: "MJF Nylon PA12", es: "MJF Nylon PA12"}, hexCode: "#FF465B", id: "5857ed97-bc6f-4e30-84c7-864d63fa2ab5", image: "https: //test.image/mjf_nylon", description: {en: "MJF Nylon PA12 English description", de: "MJF Nylon PA12 deutsche Beschreibung", es: "MJF Nylon PA12 descripción en español"}}]}]}]
console .log (chooseNestedProps (['name', 'description']) ('en') (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
But I would actually rather abstract that a bit, and use a still more general function that allows us to set the nested values of an object by passing two functions: a predicate which tests if this key/value combination should be replaces, and a tranformer that returns a new value when supplied a key and value. Then we can write chooseNestedProps
more simply atop that reusable function, something like this:
const deepMap = (pred, fn) => (o) =>
Array .isArray (o)
? o .map (x => deepMap (pred, fn) (x))
: Object (o) === o
? Object .fromEntries (Object .entries (o) .map (
([k, v]) => [k, pred (k, v) ? fn (k, v) : deepMap (pred, fn)(v)]
))
: o
const chooseNestedProps = (props) => (val) => deepMap (
(k, v) => props .includes (k),
(k, v) => v [val]
)
const input = [{name: {en: "PLA", de: "PLA", es: "PLA"}, density: 5.17, id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}, finishes: [{name: {en: "Standard", de: "Standard", es: "Estándar"}, materialId: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", colorIds: ["9704a8b0-ae94-4945-94ef-8445b387d48d", "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", "d648994f-b1fa-4982-969e-eee2f7a68c77", "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", "e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"], id: "8f529b1f-18a8-408b-a88c-b9056ef6e50e", image: "https: //test.image/pla_standard", description: {en: "PLA Standard English description", de: "PLA Standard deutsche Beschreibung", es: "PLA estándar descripción en español"}, colors: [{_id: "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", name: {en: "PLA", de: "PLA", es: "PLA"}, hexCode: "#00CC33", id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}}, {_id: "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", name: {en: "316L Stainless Steel", de: "316L Rostfreier Stahl", es: "316L Acero Inoxidable"}, hexCode: "#000000", id: "c7bc7177-8137-4552-a218-0aa4d2491373", image: "https: //test.image/316L", description: {en: "316L English description", de: "316L deutsche Beschreibung", es: "316L descripción en español"}}, {_id: "d648994f-b1fa-4982-969e-eee2f7a68c77", name: {en: "MJF Nylon PA12", de: "MJF Nylon PA12", es: "MJF Nylon PA12"}, hexCode: "#FF465B", id: "5857ed97-bc6f-4e30-84c7-864d63fa2ab5", image: "https: //test.image/mjf_nylon", description: {en: "MJF Nylon PA12 English description", de: "MJF Nylon PA12 deutsche Beschreibung", es: "MJF Nylon PA12 descripción en español"}}]}, {name: {en: "Polished", de: "Poliert", es: "Pulido"}, materialId: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", colorIds: ["9704a8b0-ae94-4945-94ef-8445b387d48d", "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", "d648994f-b1fa-4982-969e-eee2f7a68c77", "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", "e1e78350-4f7e-4d5c-9ebc-5fa3b10e7ce1"], id: "9704a8b0-ae94-4945-94ef-8445b387d48d", image: "https: //test.image/mjf_nylon_polished", description: {en: "MJF Nylon PA12 polished English description", de: "MJF Nylon PA12 poliert deutsche Beschreibung", es: "MJF Nylon PA12 pulido descripción en español"}, colors: [{_id: "d18cd8a2-e1ab-4de4-bda4-c3610d9fd93e", name: {en: "PLA", de: "PLA", es: "PLA"}, hexCode: "#00CC33", id: "32ccfa8d-8db6-41f6-83fa-7726851bffd4", image: "https: //test.image/pla", description: {en: "PLA English description", de: "PLA deutsche Beschreibung", es: "PLA descripción en español"}}, {_id: "1ba6c1ae-8c41-47f3-b925-11316afd1ddd", name: {en: "316L Stainless Steel", de: "316L Rostfreier Stahl", es: "316L Acero Inoxidable"}, hexCode: "#000000", id: "c7bc7177-8137-4552-a218-0aa4d2491373", image: "https: //test.image/316L", description: {en: "316L English description", de: "316L deutsche Beschreibung", es: "316L descripción en español"}}, {_id: "d648994f-b1fa-4982-969e-eee2f7a68c77", name: {en: "MJF Nylon PA12", de: "MJF Nylon PA12", es: "MJF Nylon PA12"}, hexCode: "#FF465B", id: "5857ed97-bc6f-4e30-84c7-864d63fa2ab5", image: "https: //test.image/mjf_nylon", description: {en: "MJF Nylon PA12 English description", de: "MJF Nylon PA12 deutsche Beschreibung", es: "MJF Nylon PA12 descripción en español"}}]}]}]
console .log (chooseNestedProps (['name', 'description']) ('en') (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
This does not use Ramda. Ramda is not particularly suited to building full recursive functions, although you could certainly use it in the implementation, replacing things like Array .isArray (obj)
and Object (obj) === obj
with is (Array)
and is (Object)
, replacing Object .fromEntries
and Object .entries
with fromPairs
and toPairs
, and using map
and includes
instead of their Array .prototype
versions. But I don't think that would clarify much.
Of course we could also write a more specific solution to your problem to as a reusable function, with something like
const chooseLanguage = (o, lang) => chooseNestedProps (['name', 'description']) (lang) (o)
// later
chooseLanguage (input, 'es')