Making a REST service using Node and Express to use with Unity - Part 3
Tags: unity3d, node, tutorial
Published: 2019-09-24 10:40:14

Greetings to all unity ninjas!

This part we'll make a POST request from a unity client to the node server. We haven't made a database, yet, so I'll make an array for now.

Start with server-side. In `app.js`, remember that we had a single enemy object, this part, I'll make an array and populate with some enemy.

```javascript
let enemies = [
	{
		"id": 0,
		"name": "orc",
		"health": 100,
		"attack": 25
	},
	{
		"id": 1,
		"name": "wolf",
		"health": 110,
		"attack": 25
	}
];
```

Next, tell express to support JSON-encoded bodies.

```javascript
app.use(express.json());
```
Next, let's make a post method to receive a request from unity client.
```javascript
app.post('/enemy/create', (req, res) => {
let newEnemy = {
	"id": req.body.id,
	"name": req.body.name,
	"health": req.body.health,
	"attack": req.body.attack
};

enemies.push(newEnemy);
console.log(enemies);
res.send(enemies);
});
```
And I'll modify my get method to fetch my `enemies` array. Now my `app.js` file looks like this:

```javascript
const express = require('express');
const app = express();
app.use(express.json());

app.get('/', (req, res) => {
    res.send('Hello Unity Developers!');
});

let enemies = [
	{
		"id": 0,
		"name": "orc",
		"health": 100,
		"attack": 25
	},
	{
		"id": 1,
		"name": "wolf",
		"health": 110,
		"attack": 25
	}
];

app.get('/enemy', (req, res) => {
    res.send(enemies);
});

app.post('/enemy/create', (req, res) => {
let newEnemy = {
	"id": req.body.id,
	"name": req.body.name,
	"health": req.body.health,
	"attack": req.body.attack
};

enemies.push(newEnemy);
console.log(enemies);
res.send(enemies);
});

app.listen(3000, () => console.log('started and listening.'));
```

Open a terminal, start node and it's time to visit unity client.

```
node app.js
```

Let's make an api call, I'll use postman.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/4s05xp31h5lltieosq5m.png)

Don't forget to set header and body to `application/json`.

Now make an enemy json string based on the enemy schema and hit to send.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/zsar1id2q4e7282jils8.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/sphg3g6131k8cisxh00i.png)

Seems our enemies growing :)

Last part, we have successfully received a json object and displayed it to screen with unity ui elements. But this part our structure has changed a bit. I've added `id` property to the enemy and my response now not an object but an array. 

First, add `id` property to `Enemy` class in unity.

```c#
public class Enemy
{
    public int id;
    public string name;
    public int health;
    public int attack;
}
```

Yeah, that was easy! But keep in mind, `JsonUtility` does not work with  `{get; set;}`.

Now the important part! If your task is to send a json array and parse in unity, there is no out of the box solution with `JsonUtility`, unfortunately. Don't worry, after a couple googling and experimenting, I found a workaround, for a detailed explanation, take a look [here](https://stackoverflow.com/questions/36239705/serialize-and-deserialize-json-and-json-array-in-unity) and [here](https://forum.unity.com/threads/how-to-load-an-array-with-jsonutility.375735/). 

For example, If your response is like this, then `JsonUtility` won't work:

```json
[
  {
  	//item
  },
  {
  	//item
  },
  {
  	//item
  }
]
```

Instead, we'll make it a single key and an array object as a value:

```json
{
	"result": [{//item},{//item},{//item}]
}
```

This way, we have a **one list** of **items** and this structure works with `JsonUtility`. 

To make this trick possible we'll make a static class named `JsonHelper`. Let's create it in the project folder. 

```c#
using UnityEngine;
using System.Collections.Generic;

public static class JsonHelper
{
    public static List<T> FromJson<T>(string json)
    {
        Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
        return wrapper.result;
    }

    [System.Serializable]
    private class Wrapper<T>
    {
        public List<T> result;
    }
}
```

`JsonHelper` class has a generic `FromJson` method that returns a list of any class we're going to make. Here key part is the `Wrapper` class that has a result list that stores the values from. In our case, when we get an array of json objects from server, we have to modify our response string like this:

```
{
	"result": [
		//enemy,
		//enemy
	]
}
```

We have discussed our schema and made a helper class to make it work, let's write some code!

First, mark the `Enemy` class as `Serializable`, so unity will be able to convert to json. More explanation [here](https://forum.unity.com/threads/terminology-what-does-serializable-mean-in-unity-terms.546241/).

```c#
[System.Serializable]
public class Enemy
{
    public int id;
    public string name;
    public int health;
    public int attack;
}
```

Second, open `ClientApi` script and make a post method. It will take two parameters, post url and an enemy object to feed in unity's post method. 

```c#
public IEnumerator Post(string url, Enemy enemy)
{
  var jsonData = JsonUtility.ToJson(enemy);
  Debug.Log(jsonData);
  
  using(UnityWebRequest www = UnityWebRequest.Post(url, jsonData))
  {

  }
}
```

We are converting an `Enemy` object to a json string with `JsonUtility`.

Next, configure our request's `content-type`.

```c#
public IEnumerator Post(string url, Enemy enemy)
{
  var jsonData = JsonUtility.ToJson(enemy);
  Debug.Log(jsonData);
  
  using(UnityWebRequest www = UnityWebRequest.Post(url, jsonData))
  {
		www.SetRequestHeader("content-type", "application/json");
    www.uploadHandler.contentType = "application/json";
    www.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(jsonData));
    
    yield return www.SendWebRequest();
  }
}
```

 We have set our method to send a json object and to a url endpoint. 

Remember that, we send back our enemies as a response after request.  So, let's make a list from the response, then display to console. Now, time to handle response end error.

```c#
// handle the result
var result = System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);  
result = "{\"result\":" + result + "}"; 
var resultEnemyList = JsonHelper.FromJson<Enemy>(result);

foreach (var item in resultEnemyList)
{
  Debug.Log(item.name);
}
```

This is the part that we have discussed above. As soon as I get data, I modified it to be able to work with `JsonHelper`.

Then just display to console each element's `name` to test. 

```c#
public IEnumerator Post(string url, Enemy enemy)
{
  var jsonData = JsonUtility.ToJson(enemy);
  Debug.Log(jsonData);
  
  using(UnityWebRequest www = UnityWebRequest.Post(url, jsonData))
  {
		www.SetRequestHeader("content-type", "application/json");
    www.uploadHandler.contentType = "application/json";
    www.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(jsonData));
    yield return www.SendWebRequest();
    
    if (www.isNetworkError)
    {
      Debug.Log(www.error);
    }
    else
    {
      if (www.isDone)
      {
        // handle the result
        var result = System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);  
        result = "{\"result\":" + result + "}"; 
        var resultEnemyList = JsonHelper.FromJson<Enemy>(result);

        foreach (var item in resultEnemyList)
        {
          Debug.Log(item.name);
        }
      }
      else
      {
        //handle the problem
        Debug.Log("Error! data couldn't get.");
      }
    }
  }
}
```

To test, define a string variable for post url, make an `Enemy` object in `Start` and switch back to unity.

```c#
public string getUrl  = "localhost:3000/enemy";
public string postUrl = "localhost:3000/enemy/create";

void Start()
{
  var enemy = new Enemy(){
    id = 100,
    name = "Balrog",
    health = 1000,
    attack = 2500
  };

  StartCoroutine(Post(postUrl, enemy));
}
```

Time to hit Play!

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/tk9jj9splrphzq80hec7.png)

Check console.log on terminal too.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fqeusdv13gycruwvhel1.png)

Good job, our unity ninja skills improved a bit more!!🎉🎉🎉🌟🌟🌟👏👏👏😎😎 

Looks like we have successfully sent data from unity client, received from the server and responded with updated data 😎👾

Grab the code [here](https://github.com/cemuka/unity-node-tutorial)

Next part we'll post with the ui element's help and to handle data in unity, we'll use Scriptable Objects.

Until the next part, cheers!