Skip to content

Instantly share code, notes, and snippets.

@burkeholland
Last active September 30, 2022 08:12
Show Gist options
  • Save burkeholland/c1119c264cec255f0d3d to your computer and use it in GitHub Desktop.
Save burkeholland/c1119c264cec255f0d3d to your computer and use it in GitHub Desktop.
Reading A Local JSON File With NativeScript

In NativeScript, the http module doesn't currently support making network requests to the local file system. That work is intended to be done by the file reader. It's pretty simple to read a local file and parse its contents as JSON.

This is the TypeScript/Promise version of what Emil Oberg created for the same question on StackOverflow. This module should be reusable for any and all asyncronous local JSON read operations.

import * as fs from 'file-system';

var documents = fs.knownFolders.currentApp();

class FileReader {
    static readJSON(path: string) {
        var jsonFile = documents.getFile(path);
        return new Promise<Object>((resolve, reject) => {
            try {
                
                jsonFile.readText().then((content: string) => {
                    let data = <Array<Object>>JSON.parse(content);
                    resolve(data);   
                });
                        
            }
            catch (err) {
                reject(err);
            }
        });
    }   
}

export default FileReader;
@deadelus
Copy link

Hi, how can I use it correctly in my views ? Because, an error occured when I'm loaded my view.
My view:

var FileReader = require("../../shared/utils/file-reader/file-reader");

function pageLoaded(args) {
    var page = args.object;
    FileReader.readJSON("/res/test/test.json")
    .then(function(response){
        console.log(JSON.stringify(response));
    }, function(error){
        console.log(JSON.stringify(error));
    });
}

JS ERROR TypeError: FileReader.readJSON is not a function. (In 'FileReader.readJSON("/res/test/test.json")', 'FileReader.readJSON' is undefined)

Thx you for this FileReader :)

@deadelus
Copy link

I adapted your code, it's working fine ! But I really want to see your example.

file-reader.js

var fs = require('file-system');
var documents = fs.knownFolders.currentApp();

module.exports = {
    readJSON: function (path) {
        var jsonFile = documents.getFile(path);
        return new Promise(function (resolve, reject) {
            try {
                jsonFile.readText().then(function (content) {
                    var data = JSON.parse(content);
                    resolve(data);
                });
            }
            catch (err) {
                reject(err);
            }
        });
    }
};

home.js

var observable = require("data/observable");
var frameModule = require("ui/frame");

// Plugins
var FileReader = require("../../shared/utils/file-reader/file-reader");

function pageLoaded(args) {
    var page = args.object;

    FileReader.readJSON("test.json")
    .then(function(response){
        console.log(JSON.stringify(response));
    }, function(error){
        console.log(JSON.stringify(error));
    });
}

exports.pageLoaded = pageLoaded;

@shangab
Copy link

shangab commented Aug 24, 2016

Can you guys crunch this URL as json object in Nativescript?
https://api.spotify.com/v1/search?offset=0&limit=30&market=US&query=john&type=artist
Thanks for showing me,

@shangab
Copy link

shangab commented Aug 24, 2016

Can someone tell me how to do this in Angular2 and Nativescript?

Here is my code:

spotify.service.ts:

`import {Injectable} from '@angular/core'
import {Http, Headers} from '@angular/http';
import 'rxjs/add/operator/map';
//import {NSHttp} from 'nativescript-angular/http';
@Injectable()
export class SpotifyService {
private artistsUrl: string = 'https://api.spotify.com/v1/search?offset=0&limit=30&market=US&query=';
private tsturl: string = 'https://api.spotify.com/v1/search?offset=0&limit=30&market=US&query=john&type=artist';
private artistUrl: string = 'https://api.spotify.com/v1/artists/';
private albumUrl: string = 'https://api.spotify.com/v1/albums/';

constructor(private _http: Http) {

}

searchMusic(searchStr: string, type: string = 'artist') {
    return this._http.get(this.artistsUrl + searchStr + "&type=" + type).map(res => res.json());
    //return this._http.get(this.tsturl).map(res => res.json());
}

getArtist(id: string) {
    return this._http.get(this.artistUrl + id).map(res => res.json());
}

getAlbums(id: string) {
    return this._http.get(this.artistUrl + id + "/albums").map(res => res.json());
}

getAlbum(id: string) {
    return this._http.get(this.albumUrl+id).map(res => res.json());
}

}`

And here is where I use it search.component.ts:

`import { Component } from '@angular/core';
import {SpotifyService} from '../../services/spotify/spotify.service';

import {Artist} from '../../types/artist';

@component({
moduleId: module.id,
selector: 'search',
templateUrl: 'search.component.html',
providers:[SpotifyService]

})
export class SearchComponent {
private srchtxt:string;
private searchRes:any[];
private searchResStr:string;

constructor(private _spoSer:SpotifyService){

}
searchMusic(searchStr:string){
    this._spoSer.searchMusic(searchStr).subscribe(res=>{
        this.searchRes=res.artists.items;
        this.searchResStr= JSON.stringify(this.searchRes);
    });
}

onSetupItemView(ev:any){

}

}`
And here is my seach.component.html that does not work:

`

<TextField hint="Search artists" #srchstr (keyup)="searchMusic(srchstr.value)">
<Button text="Search..." (tap)="searchMusic(srchstr.value)">
<ListView [items]="searchRes" (setupItemView)="onSetupItemView($event)">


<Label [text]='ar.name'>


</StackLayout>

`

And here is what it says:

Cannot read property 'name' of undefined

OOUUTCH

@toddanglin
Copy link

toddanglin commented Dec 15, 2016

FWIW...I also modified Burke's original slightly. Here's what I'm using:

import * as fs from "file-system";
let documents = fs.knownFolders.currentApp();

export class FileReader {
    public static readJSON(path: string): Promise<Object> {
        let jsonFile = documents.getFile(path);
        return new Promise<Object>((resolve, reject) => {
            jsonFile.readText().then((content: string) => {
                let data = <Array<Object>>JSON.parse(content);
                resolve(data);
            })
            .catch((err) => {
                reject(err);
            });
        });
    }
}

To use this somewhere in app code:

import { FileReader } from "../path/to/fileReader";
FileReader.readJSON("data/file.json")
                .then((response) => {
                    resolve(response);
                })
                .catch((err) => {
                    reject(err);
                });

Hope it helps someone. Note the path to the JSON file is always relative to the root app directory.

@srnaik
Copy link

srnaik commented Feb 14, 2017

I am trying to parse a local JSON file and add/push its content to an array named sideDrawerItemsFromJson, but when I try to push the JSON content to thi sarray, I am getting a null pointer exception. I have initialized this array in the beginning, I dont know where I am missing the trick, please look into it,Thanks

var fs = require('file-system');
var documents = fs.knownFolders.currentApp();
var jsonFile = documents.getFile('pages/shell-drawer/Shell.json');
var jsonData;
let drawerItem;

jsonFile.readText().then(function (content) {
    try {
        console.log("JSON Content to parse: " + "\n" + content);
        jsonData = JSON.parse(content);
        let data = <Array<Object>>JSON.parse(content);
        console.log("Number of Menu Group Items: " + jsonData.SideDrawerItems.length);

        for (let j = 0; j < jsonData.SideDrawerItems.length; j++) {

            drawerItem = new SideDrawerMenuItem(jsonData.SideDrawerItems[j].name, jsonData.SideDrawerItems[j].sideDrawerChildItems, jsonData.SideDrawerItems[j].hasChild);
            console.log("Menu Group Name is: " + drawerItem.name + "\n");
            console.log("This Menu Group Has " + drawerItem.sideDrawerChildItems.length + " Menu Items ");
            for (let k = 0; k < drawerItem.sideDrawerChildItems.length; k++) {
                console.log("Menu Item Name " + drawerItem.sideDrawerChildItems[k].name + "\n");
            }

            //TODO - Implement a most suitable to add parsed JSON Objects an array Object(Instance/Class variable).
            this.sideDrawerItemsFromJson.push(drawerItem);
        }

    } catch (err) {
        console.log('Could not parse JSON file' + err.toString());
    }
}, this.handleErrors);

@DrMabuse23
Copy link

const A = require('./assets/my.json');
have fun

@dean-huczok
Copy link

dean-huczok commented Mar 5, 2018

move this line let jsonFile = documents.getFile(path); inside the let{} so if the JSON file doesn't exist, the thrown error is caught and returned with the Promise.

Also to note, the file path always defaults to the app root, not the current file directory. :)

Personally I added this method into my own little Utility class, works a treat. Returns raw JSON data so that other functions that call this method can parse the JSON through different interfaces (so JSON data is output as a specific type of object). Here's my code:

import * as fs from 'file-system';

export default class Utility {
   static loadJSON(path: string) {
	let documents = fs.knownFolders.currentApp();
	return new Promise<Object>((resolve, reject) => {
		try {
			let jsonFile = documents.getFile(path);
			resolve( jsonFile.readText() )					
		}
		catch (err) {
			reject(err);
		}
	});
   }

}

@NickIliev
Copy link

NickIliev commented Nov 20, 2018

With TypeScript 2.9.x and above we can now use resolveJsonModule and directly treat JSON files as modules. Sample project here.

Example

// config.json
{
    "count": 42,
    "users": [
        {"name": "John", "age": 35},
        {"name": "Ann", "age": 32},
        {"name": "George", "age": 24},
        {"name": "Mary", "age": 27},
        {"name": "Vivian", "age": 21}
    ],
    "env": "debug"
}
// your-typescript-file.ts
import config from "./config.json";

console.log(config.count); // 42
console.log(config.env); // "debug"
// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment