0

I am getting the following object from API call:

{
    "email": ["The email has already been taken."],
    "profile_image": [ "profile image is requried." ]
}

I used the following code to iterate over this object (using for...of):

let message = "";
for (const [error_name, error_value, i] of Object.entries(
  error.response.data.errors
)) {
  message += `${i}: ${error_value[0]}\n`;
}

But I am getting undefined instead of getting the value of i. I want to get the iteration number.

Any suggestions?

5
  • 1
    Object.entries returns a 2d array, where the inner arrays represent key-value pairs ([key, value]), so you can't destructure a value i which isn't in this inner-array Commented Jul 31, 2019 at 11:51
  • Why are you not just using forEach or map or even better reduce? Commented Jul 31, 2019 at 11:51
  • You can use .entries() to get indices in a for..of loop Commented Jul 31, 2019 at 12:00
  • @JonasWilms like error_value.entries()??? Commented Jul 31, 2019 at 12:03
  • for const [index, [error_name, error_value]] of Object.entries( error.response.data.errors ).entries()) Commented Jul 31, 2019 at 12:06

2 Answers 2

4

An Object.entries item will only contain two values: the key and the value. If you want the index as well, you'll have to implement it yourself or use another strategy. One option is use forEach to iterate over the array instead (the second argument forEach takes is the current index):

let message = "";
Object.entries(error.response.data.errors)
  .forEach(([error_name, error_value], i) => {
    message += `${i}: ${error_value[0]}\n`;
  });

You can also avoid the let for message by using .map/.join:

const message = Object.entries(error.response.data.errors)
  .map(([error_name, error_value], i) => `${i}: ${error_value[0]}`)
  .join('\n');

(unlike your original code, this will not have a trailing newline at the end, but that's probably a good thing)

Sign up to request clarification or add additional context in comments.

4 Comments

Bro can you tell me if there is only 1 element in the object then don't display ${i}: part.
I'd save the entries in a variable and use the conditional operator. const message = errorEntries.length === 1 ? errorEntries[1] : entries.map(...code in answer...)
Bro the 3rd param is the obj which get passed I wrote, const message = Object.entries(error.response.data.errors) .map(([error_name, error_value], index, obj) => Object.keys(obj).length == 1 ? ${error_value[0]} : ${index + 1}: ${error_value[0]} ) .join("\n");
Much better to save the entries in a variable first, rather than to try to stuff it all into a single assignment expression
0

The iterator from Object.entries only produces two-place arrays in the form [key, value]. There is no third entry in those arrays.

In general, objects should be considered unordered, so it's not clear why you want an index. But if you do, since you're building a string with concatenation, you could use map on the Object.entries array instead:

let message =
    Object.entries(error.response.data.errors)
    .map(([error_name, error_value], i) => `${i}: ${error_value[0]}\n`)
    .join("");

Live Example:

const error = {
    response: {
        data: {
            errors: {
              "email": ["The email has already been taken."],
              "profile_image": [ "profile image is requried." ]
            }
        }
    }
};
let message =
    Object.entries(error.response.data.errors)
    .map(([error_name, error_value], i) => `${i}: ${error_value[0]}\n`)
    .join("");
console.log(message);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.