Alcinos
February 9, 2022, 10:37pm
1
I’m using version 4.0.6 and have a user management system implemented.
Thing is, when have a deep relation, accesing the data from the frontend can be really verbose.
for example accesing the name of a neighborhood of a client in a city is
city.data.attributes.client.data.attributes.neighborhood.data.attributes.name
So i have to map through to simplify the data, like this
const ticketList = tickets.data.map((ticket) => {
ticket.attributes.id = ticket.id
ticket.attributes.client.data.attributes.id = ticket.attributes.client.data.id
ticket.attributes.client = ticket.attributes.client.data.attributes
ticket.attributes.city.data.attributes.id = ticket.attributes.city.data.id
ticket.attributes.city = ticket.attributes.city.data.attributes
ticket.attributes.client.neighborhood.data.attributes.id = ticket.attributes.client.neighborhood.data.id
ticket.attributes.client.neighborhood = ticket.attributes.client.neighborhood.data.attributes
ticket.attributes.client.technology.data.attributes.id = ticket.attributes.client.technology.data.id
ticket.attributes.client.technology = ticket.attributes.client.technology.data.attributes
ticket.attributes.tickettype.data.attributes.id = ticket.attributes.tickettype.data.id
ticket.attributes.tickettype = ticket.attributes.tickettype.data.attributes
ticket.attributes.assignated.data.attributes.id = ticket.attributes.assignated.data.id
ticket.attributes.assignated = ticket.attributes.assignated.data.attributes
ticket.attributes.ticketdetails.data.forEach((ticketdetail) => {
ticketdetail.attributes.id = ticketdetail.id
ticketdetail = ticketdetail.attributes
})
return ticket.attributes
})
Is there an option or a method to deal with this long nested responses in an more elegant way?
i was triying to made a function to flat the object but i thinks maybe there is a better way to do this.
2 Likes
I came here to ask this same question.
I have created a sanitizeApiResponse
function that looks like:
export const sanitizeApiResponse = (response) => {
if (!response || !response.data) {
return undefined
}
if (Array.isArray(response.data)) {
const sanitized = response.data.reduce(
(acc, curr) => {
const item = {
id: curr.id,
...curr.attributes,
}
acc.push(item)
return acc
},
[],
)
return sanitized
}
const sanitized = {
id: response.data.id,
...response.data.attributes,
}
return sanitized
}
This transforms:
{
data: [
{
id: 1,
attributes: {
item1: 'foo',
item2: 'bar',
},
},
],
}
Into:
{
id: 1,
item1: 'foo',
item2: 'bar',
}
It also works when the response doesn’t have an array in data
This works pretty well for basic responses but the issue comes in when we have relations or components as we have to run the same function over and over again on each relation.
It’s a pretty nasty way to have to deal with things. It feels wrong that so much sanitization needs to be performed client side.
If anyone knows of a more elegant way then let us know!
1 Like
I done this :
const sanitizeResults = (response) => {
if (!response || !response.data || !Array.isArray(response.data)) {
return []
}
return response.data.map(item => {
let sanitized = sanitizeObject(item)
return sanitized
})
};
const sanitizeObject = (item) => {
let sanitized = {}
if (!item || typeof item !== 'object') {
return sanitized
}
for (const [key, value] of Object.entries(item)) {
if (key === 'id') {
sanitized[key] = value
}
else if (key === 'attributes') {
for (const [keyAttribute, valueAttribute] of Object.entries(item[key])) {
if (typeof item[key][keyAttribute] === 'object' && item[key][keyAttribute]) {
sanitized[keyAttribute] = sanitizeObject(valueAttribute.data)
} else {
sanitized[keyAttribute] = valueAttribute
}
}
}
}
return sanitized
}
export { sanitizeResults, sanitizeObject };
I’ve made some improvement to it.
function sanitizeObject(item) {
let sanitized = {};
if (!item || typeof item !== "object") {
return sanitized;
}
if (Array.isArray(item)) {
return item.map(sanitizeObject);
}
for (const [key, value] of Object.entries(item)) {
if (key === "id") {
sanitized[key] = value;
} else if (key === "attributes") {
for (const [keyAttribute, valueAttribute] of Object.entries(
item[key]
)) {
if (
typeof item[key][keyAttribute] === "object" &&
item[key][keyAttribute]
) {
if ("data" in valueAttribute) {
sanitized[keyAttribute] = sanitizeObject(
valueAttribute.data
);
} else {
sanitized[keyAttribute] =
sanitizeObject(valueAttribute);
}
} else {
sanitized[keyAttribute] = valueAttribute;
}
}
} else {
sanitized[key] = value;
}
}
return sanitized;
}