Back to homepage

Solidity fundamentals: complex data types

Published

Continuation of the previous article about data types, now reviewing complex way to store and handle data using structs, arrays and mappings.


Check out my previous article about simple data types in Solidity

Structs

Structs are used to define complex data types with multiple variables, known as properties of the struct. They're defined with the struct keyword:

struct Pokemon {
  string name;
  uint stamina;
  uint power;
  bool owned;
}

Once we've defined a struct, we can create new variables of this type by using the name of the struct as our constructor method and pass it the properties it has in the same order they're defined:

// create a New Pokemon indicating the name, stamina, power and owned
Pokemon pikachu = Pokemon('pikachu', 10, 7, false);

Arrays

Arrays are used to group a bunch of variables of the same type and they're declared with the type of the variables it'll hold and two brakets []. In addition, there are two types of arrays in Solidity: dynamic arrays and fixed arrays. When declaring the latest, we'd need to indicate the lenght of the array as show below 👇

// Array with a fixed length of 4 elements, can contain 2 numbers
uint[4] numbersArray;
// can contain 7 strings
string[7] stringsArray;
// a dynamic Array - has no fixed size, can contain numbers and keep growing
uint[] numbersDynamicArray;

Push and read items from array

To push items into an array we use the push() method and pass it the item we want to include in the array, keeping in mind that it has to be of the specific type our arra was declared:

// a dynamic Array - has no fixed size, can contain numbers and keep growing
uint[] numbersDynamicArray;

// adds the number 3
numbersDynamicArray.push(3);
uint number = 7;
// adds number 7
numbersDynamicArray.push(number);


It's important to notice that the push method will add a new item to the array at the end of it.

To read data from an array in Solidity, we'll use the braket notation and indicate the index of the element of the array we want to read, keeping in mind that the first item will be the index 0:

uint[] numbers = [1,3,5,7,9];
// seven will have the forth item of the array, a 7
uint seven = numbers[3]

Array of structs

In Solidity, arrays can hold simple data types (integers strings, or booleans...) as in the example above, but they can also hold structs. To define an array of structs in Solidity you have to follow the same pattern:

struct Pokemon {
  string name;
  uint stamina;
  uint power;
  bool owned;
}

Pokemon[] pokemonCollection; // dynamic Array of Pokemons

To add and read data from an array of structs, you'll follow the same patter as with any other array, with the push() method and the braket notation ([]) passing the index of the item we want to read:


Pokemon[2] pokemonCollection; // dynamic Array of Pokemons

Pokemon pikachu = Pokemon('pikachu', 10, 7, false);
Pokemon charmander = Pokemon('charmander', 9, 8, true);

// push items into the array
pokemonCollection.push(pikachu);
pokemonCollection.push(charmander);

// read charmander
pokemonCollection[1]


Public Arrays

Arrays can be declared as public, and Solidity will automatically create a getter method for it. The syntax looks like:

Person[] public people;

Once an array is declared public, other contracts will be able to read from it but not write to it. This is a useful pattern for storing public data in your contract.

I'll explain more about public/private variables in another article.

Mappings

Mappings are another way of storing organized data in Solidity and they're defined with the mapping keyword. They are key-value pairs for storing data; the key should be a simple data type (address, uint, bytes, string) while the value can be a single or complex data type like an array or struct. They're easier to understand with an example 😉

// Or could be used to store / lookup usernames based on userId
mapping (uint => string) userIdToName;
// App that has multiple users and each user has a collection of Pokemons
mapping(string => Pokemon[]) public pokemonCollections

In the first example, the key is a uint and can represent the id of a user and the value a string and will contain the user's name. In the second example the key is the name of each user as a string, and the value will be an array of Pokemons (the struct we defined earlier).

To read data from the mapping we use the braket notation and pass the key:

// get the name of the user with id 3
string name = userIdToName[3]
// get Adam's pokemon collection
Pokemon[] col = pokemonCollections['Adam']

TAGS


If you enjoyed this article consider sharing it on social media or buying me a coffee ✌️

Buy Me A Coffee