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:
{ "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 ...
{ "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 ...
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 ...
{ "features": { "enableKonami": true, "enableTheme": true, ... "useLocalJSON": false } }
The file can then be imported like this ...
import config from '@core/constants/config.json';
And used like this ...
if (config.features.useLocalJSON === true) { ... }
config
in this sense can be included in a component, as such, to be used in HTML.
@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 ...
{ "english": { "config": "Configuration", "header": "Header", ... } }
The file can then be imported like this ...
import language from '@core/constants/language.json';
And used like this ...
@Component({ ... }) export class CardFunctionalityComponent implements OnInit { ... selectedLanguage: string = 'english'; language: any = language[selectedLanguage]; ... }
Host Names
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 ...
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.
{ "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 ...
[ { "selected": false, "id": "1", "lastname": "Fornal", "firstname": "Bob" }, ... ]
We can ...
- Set the order when displayed on a table
- Enable proper sorting of the data
- Display proper column names
- Decide whether to display the column or not
- 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.
Top comments (0)