JavaScript Objects and Arrays Manipulation for REST API

Viacheslav Luschinskiy
7 min readJan 19, 2020

--

JavaScript objects and arrays manipulation can be complex but it is the essential part of any frontend application that deals with REST API. It can become even more complex if you add immutability requirement imposed by the most modern JavaScript frameworks like React and Angular.

From the other hand when working with REST API you do mostly the same things like CRUD operations (Create, Read, Update, Delete) and some other transformations, so you don’t have to learn everything about objects and arrays before you start building the apps.

In this article I will show how to professionally manipulate objects and arrays with the modern JavaScript including ES2020, as well as with the most popular Lodash library in the scope of the common REST API tasks. I’ll skip all the basics and focus on the more complex and interesting parts.

Do we still need Lodash or we can get away with just the modern JavaScript? That is the question that we will try to answer at the end of this article as well.

You can play with all the examples in this article by cloning the accompanying git repo.

Let’s now see how we can read and send data to the backend REST API. We will first have a look at how to do all the CRUD operations and then move on to the more complex transformations. We will start with reading operation.

READ

Before we can read something we first need to check if there is something. The tricky part here is that even empty array and object will result to ‘true’ when doing something like this:

const emptyArray = []
!!emptyArray
// => true

Therefore, you need to check the length property instead:

myArray.length === 0 
Object.entries(myObject).length === 0

The chances are that your backend guys instead of sending the empty array or object will send nothing, so you’d better do a bit more complex check:

myArray && myArray.length === 0
myObject && Object.entries(myObject).length === 0

If you are not a person that loves strict typing, you can do it a bit shorter:

!!( myArray && myArray.length)
!!( myObject && Object.entries(myObject).length)

Now let’s see how we can do this check with Lodash. Lodash is the library, which has many functions that simplify common array, object and functions manipulations. When you import Lodash from the external module you usually refer to it as _ (underscore sign).

_isEmpty(myArrayOrObject)

Quite simple, right? That is why (some) people love Lodash.

Now lets try to read some value from the (deeply) nested object. For example we have the object like this:

const nestedObject = {
key1:
{
key2:
{
key3: 'value3',
key4: 'value4'
}
}
}

You can’t just write nestedObject.key1.key2.key3 since if there is no key2, then trying to read key3 may crash your app. Therefore you should do something like this:

a) Good old way, which would probably work with the first version of JavaScript:

nestedObject && nestedObject.key1 && nestedObject.key1.key2 && nestedObject.key1.key2.key3

b) A brand new ES2020 way that can be currently (January 2020) used only with the babel or node 13+ with the ‘harmony’ flag:

nestedObject?.key1?.key2?.key3

c) With Lodash

_.get(nestedObject, 'key1.key2.key3')

Sometimes, if the key you are looking for does not exist you want to have some default value. In this case you need to modify above mentioned examples a bit like this:

a) nestedObject && nestedObject.key1 && nestedObject.key1.key2 && nestedObject.key1.key2.key5 || 'default value'

b)
nestedObject?.key1?.key2?.key5 ?? 'default value'

c)
_.get(nestedObject, 'key1.key2.key5', 'default value')

Another thing you need to know about the objects is that if your key is variable rather than a string, than instead of . you need to use [] like this

nestedObject[keyVar]

That is all you really need to know to read the data that usually comes from the REST API. Lets move to create operation.

CREATE

Creating something is quite simple:

const myArray = ['a', 'b', 'c', 'd']
const myObject = {key1: 'value1', key2: 'value2'}

What you need to keep in mind though is that if you need to create a new array/object based on the existing one don’t do like this:

const newObject = myObject (Wrong!)

Remember, whatever you do, you should Not mutate (change) the existing object/array but rather create a new one. Use spread operator like this instead:

const newArray = [...myArray] (Right!)
const newObject = {...myObject} (Right!)

This will create a so called shallow copy, that is, the copy which is only one level deep independant of the old object. This should be enough for the purpose of creating a new object. If then you want to futher change some nested keys, read the Update section below.

UPDATE

To update the array you also use the spread operator:

const updatedArray = [...oldArray, 'd']

To add a new key to the object, or to change the existing key use the same approach:

const updatedObject = {...oldObject, newOrExistingKey: 'newValue'}

But updating the key of a deeply nested object can be tricky. With our example above of the 3 level deep nestedObject it will look like this:

const updatedObject = {
...nestedObject,
key1: {
...nestedObject.key1,
key2: {
...nestedObject.key1.key2,
key3: 'newValue'
}
}
}

Alternatively, you can use Lodash to Deep Copy the original object and then change the single property:

const clonedObject = _.cloneDeep(nestedObject)
clonedObject.key1.key2.key4 = 'newValue'

DELETE

Delete operations are a bit more complex. To delete something from the array you should use the filter function. In the example below we remove value ‘a’ and the third element form the myArray

const myArray = ['a', 'b', 'c', 'd']
myArray.filter((element, index) => element !== 'a' && index !== 2 )
// => [ 'b', 'd' ]

Or the same with Lodash

_.filter(myArray, (element, index) => element !== 'a' && index !== 2)

To delete some key(e.g. key1) from the object, spread operator comes to help us again:

const{key1, ...modifiedObject} = myObject

Or the same with Lodash:

const modifiedObject = _.omit(newObject, 'key2')

Deleting the nested key with JavaScript can be tricky but as far as REST API is concerned, deleting the key is the same as assigning it the undefined value. So you can use the same tools as in the Update section or use the Lodash omit helper which can delete the nested keys as well.

Object < — > Array Transformations

Now let’s have some real fun. Backend guys are not always nice. They may send you the array of objects while you want the object with the element’s IDs as the keys or the other way round. You may try to negotiate with them but it may be easier to except the reality and transform what you received from backend to what you need in frontend.

Let’s say we received the nested object like this:

const objectToTransfer = {
a: {name: 'Mary', surname: 'Poppins', age: 40},
b: {name: 'John', surname: 'Smith', age: 35},
}

But we want the array of objects like this:

const sortedArray = [
{ key: b, name: 'John', surname: 'Smith', age: 35 },
{ key: a, name: 'Mary', surname: 'Poppins', age: 40 }
]

Why we may want this? Because we want to sort the objects by age. We can achieve it by this magic expression:

const sortedArray = Object.entries(objectToTransfer)
.map(([ key, value ]) => ({key, ...value}))
.sort((a,b) => a.age - b.age)

If you do not need the keys to be part of the object, you can get away with the simpler expression:

Object.values(objectToTransfer).sort((a,b) => a.age - b.age)
// => [
{ name: 'John', surname: 'Smith', age: 35 },
{ name: 'Mary', surname: 'Poppins', age: 40 }
]

This simpler result can be achieved by Lodash as well:

const TransferredArray = _.values(objectToTransfer)
const sortedArray = _.sortBy(TransferredArray, 'age')

There is the option to chain the functions in Lodash but it requires extra effort that are probably not justified in this example. You may get more info in the Lodash docs.

Now let’s see how to make the reverse transformation from an array to an object. To do this we first need to decide what our key will be. In the example below we obviously pick the value of ID as a key. So we have the array:

const arrayToTransfer = [
{id: 'a', name: 'Mary', surname: 'Poppins', age: 40},
{id: 'b', name: 'John', surname: 'Smith', age: 35}
]

And we want the object:

const objectWeWant = {
a: { name: 'Mary', surname: 'Poppins', age: 40 },
b: { name: 'John', surname: 'Smith', age: 35 }
}

And the magic transformation is done with the help of the reduce function:

const objectWeWant = arrayToTransfer.reduce((result, {id, ...rest}) => ({...result, [id]: rest}), {} )

Don’t worry if it does not make sense to you right away. Reduce function is considered to be one of the most complex one in Array operations. I will leave it to you to figure out how it works. If you do — congratulations. You are now a JavaScript Ninja:)

If you don’t really feel comfortable with it, there is a help coming from Lodash again:

const objectWeWant = _.keyBy(arrayToTransfer, 'id')

Why do you need to transfer an array to an object? The main use case is to easily refer to the nested object by ID. If you don’t want to bother with this transformation you can still use the find function for the same purpose like this:

const objectByID = arrayToTransfer.find(obj => obj.id === 'a')

Or with Lodash helper:

const objectByID = _.find(arrayToTransfer, {id: 'a'})

Now you have the tools you need to effectively read, process or send data to/from REST API. If you think I missed some essential piece of information, please feel free to comment.

Now to the question I mentioned in the beginning. To lodash or not to lodash?

That should depend on your level of JS skills. The less dependencies your app has, the faster it works and downloads, which also means the better SEO rating. But Lodash takes care of all the edge cases for you and makes it much safer to play with arrays and objects. After all, the properly working app is still better than the fast but buggy app. So assess your JS skills and make the decision.

--

--