Rob Streeting
Rob Streeting

Reputation: 1735

What is the best way to load JSON from a dynamic filename in node.js & Typescript?

I am creating a simple web application with node.js and Typescript to build my familiarity with it, and I want to know the best way to load a JSON config file whose filename is determined at runtime.

I have found a few suggestions online:

The first approach appears like it should work, but the second seems a lot neater. The problem is that with the second approach, I have the following error:

An import declaration can only be used in a namespace or module. ts(1232)

because I want to import the file in a constructor with a filename specified as an argument. Secondly I get the following error if I try to append the given filename to the constant directory I want to get it from:

';' expected. ts(1005)

Here is a (non-compiling) code snippet from the class in which I'm trying to load the JSON, and an example JSON file that I'm trying to load in.

Typescript class:

import Floor from './Floor'
import Elevator from './Elevator'
import Person from './Person'

class Building {

    public name: string
    private floors: Floor[]
    private elevators: Elevator[]
    private people: Person[]
    private time: number

    constructor(config_filename: string) {
        import * as config from '../config/'+config_filename
        const building = (<any>config).building
        this.name = name
        this.floors = []
        building.floors.forEach((floor) => {
            this.floors.push(new Floor(floor.number, floor.name))
        })
        this.elevators = []
        building.elevators.forEach((elevator) => {
            this.elevators.push(new Elevator(elevator.name, elevator.weight_capacity, elevator.start_floor_no, this))
        })
        this.people = []
        building.people.forEach((person) => {
            const person_instance = new Person(person.name, 10, person.algorithm)
            this.people.push(person_instance)
            this.floors[person.start_floor_no].addOccupant(person_instance)
        })
        this.time = 0
    }
...

Example JSON config file:

{
    "building": {
        "name": "Basic Inc.",
        "floors": [
            {
                "number": 0,
                "name": "Ground Floor"
            },
            {
                "number": 1,
                "name": "1st Floor"
            }
        ],
        "elevators": [
            {
                "name": "Bruce",
                "weight_capacity": 100,
                "start_floor_no": 0
            }
        ],
        "people": [
            {
                "name": "Wendy Fox",
                "start_floor_no": 0,
                "algorithm": "desk"
            }
        ]
    }
}

Should I stick with the first approach, or is there some neater way to load the JSON file with a filename only known at runtime?

Upvotes: 4

Views: 6837

Answers (1)

Tobin
Tobin

Reputation: 2018

In your example, the import statement applies to when the TS is 'compiled' into JS, not at runtime with new Building(<name>) (when the code is actually executed, after compilation by the Node process).

Option 1 is a good way to do it for Node. I imagine you're trying to get away from the awkward fs functions.

Another option is to use a GET request from the code to itself, although it is ostensibly the same, you can easily explore the async / await functions which are a bit neater*.

*(last time a few months ago I used fs I did try but failed to get it going with async/await, but possibly this has changed now?)

Upvotes: 2

Related Questions