Using JSON in Angular
Tags: json, angular, settings, configuration
Published: 2021-08-09 14:40:17

---
title: Using JSON in Angular
published: true
description: Being able to import and process JSON files provides a whole host of configuration options, as well as providing a means of capturing data locally for development purposes.
tags: JSON, Angular, Settings, Configuration
series: Angular
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8iy1egkzbk6utq8pb3ix.png
---

Being able to import and process JSON files provides a whole host of configuration options, as well as providing a means of capturing data locally for development purposes.

When I started using this pattern, I was looking for a means to provide basic configuration (i.e. Feature Flags). The process quickly evolved into ...

* Authorization
* Configuration (Feature Flags)
* Language
* Host Names
* Core Structures (think titles matching data keys)

But first, I needed to be able to read these files.

## Importing and Reading JSON files

In the `tsconfig.json` file I added the `"resolveJsonModule": true` configuration option under the `compilerOptions` key:

```JSON
{
  "compileOnSave": false,
  "compilerOptions": {
    ...
    "resolveJsonModule": true,
    ...
}
```

Additionally, I learned that I can read a JSON file that is in the `assets` folder via an `http.get` request. This provided a whole host of options for development purposes.

Now, let's look at some code.

## Authorization

Basically, I built several keys and associated information for ...

* localhost
* Development
* Stage
* Production

The JSON file looks something like this ...

```JSON
{
  "localhost": {
    "issuer": "https://identity ....",
    "clientId": "..."
  },
  "application.apps.cf.np.gc ...": {
    "issuer": "https://identity ...",
    "clientId": "..."
  },
  "application-stg.apps.cf.gc ...": {
    "issuer": "https://identity ...",
    "clientId": "..."
  },
  "application-ui.apps.cf.gc ...": {
    "issuer": "https://identity ...",
    "clientId": "..."
  }
}
```

Additionally, I added code to look at the base URL and determine which of these "keys" to use.

In the `app-routing.module.ts`, the code added looks like this ...

```typescript
import authnames from '@core/constants/auth.json';

const hostnameService = new HostnameService();
const hostname = hostnameService.get(window);

if (authnames[hostname] === undefined) {
  console.error('Issue with auth.json, hostname: ', hostname);
}

const authConfig = {
  issuer: authnames[hostname].issuer,
  clientId: authnames[hostname].clientId,
  ...
};
```

## Configuration

Using the following in a `config.json` file ...

```json
{
  "features": {
    "enableKonami": true,
    "enableTheme": true,
    ...
    "useLocalJSON": false
  }
}
```

The file can then be imported like this ...

```typescript
import config from '@core/constants/config.json';
```

And used like this ...

```typescript
if (config.features.useLocalJSON === true) {
  ...
}
```

`config` in this sense can be included in a component, as such, to be used in HTML.

```typescript
@Component({
  ...
})
export class CardFunctionalityComponent implements OnInit {
  ...
  features: any = config.features;
  ...
}
```

## Language

Using the following in a `language.json` file allows for quick switching between languages, and puts all strings in one location for easy management ...

```json
{
  "english": {
    "config": "Configuration",
    "header": "Header",
    ...
  }
}
```

The file can then be imported like this ...

```typescript
import language from '@core/constants/language.json';
```

And used like this ...

```typescript
@Component({
  ...
})
export class CardFunctionalityComponent implements OnInit {
  ...
  selectedLanguage: string = 'english';
  language: any = language[selectedLanguage];
  ...
}
```

## Host Names

```typescript
getURL = (key: string): string => {
  if (this.useLocalJSON) {
    return hostnames.localJSON.BASE + hostnames.localJSON[key];
  } else {
    let hostname: string = this.hostnameService.get(window);
    return hostnames.HOSTNAMES[hostname] + hostnames.ROUTES[key];
  }
};
```

The `hostnameService.get` does something like this ...

```typescript
get = (_window) => _window?.location?.hostname;
```

I did this simply to make the code more testable.

## Core Structures

Core structures are a but harder to define.

I use these to define things like:

* Headers for table columns that match the expected data.
* Order of the columns.
* Visibility of individual columns (allowing them to be displayed or not).

Let's look at some code to see where this is going.

```json
{
  "ORDER": [
    "selected",
    "id",
    "lastname",
    "firstname"
    ...
  ],

  "SORTING": {
    "id": "number",
    "lastname": "string",
    "firstname": "string",
    ...
  },

  "COLUMNS": [
    { "id": "selected", "name": "Selected", "isActive": false },
    { "id": "id", "name": "Event Id", "isActive": true },
    { "id": "lastname", "name": "Last", "isActive": true },
    { "id": "firstname", "name": "First", "isActive": true },
    ...
  ],

  "DEFAULT": {
    "defaultSortParams": [ "lastname", "firstname" ],
    "defaultSortDirs": [ "asc", "asc" ]
  }
}
```

Now, looking at this it is clear that if we have data coming in such as ...

```javascript
[
  { "selected": false, "id": "1", "lastname": "Fornal", "firstname": "Bob" },
  ...
]
```

We can ...

1. Set the order when displayed on a table
2. Enable proper sorting of the data
3. Display proper column names
4. Decide whether to display the column or not
5. Enable default sorting options

This is a lot of functionality that can be packed into a structure file.

## Summary

Being able to import JSON files can make development easier, more efficient, and overall a better experience when used correctly.

Being able to import and process JSON files can make development easier, more efficient, and overall a better experience when used correctly. It provides a whole host of configuration options, as well as providing a means of capturing data locally for development purposes.