How do I read and write to a JSON file in DataFolder?

I would like to save user preferences selected in my plugin’s panel to the DataFolder. I haven’t found any complete examples of this in the docs.

My top-level needs are:

  1. Create a ‘settings.json’ file in DataFolder if it doesn’t exist.
  2. If it does exist, read its contents.
  3. Write new content into it and save to disk.

My xd-storage-helper library essentially does that. Since it is open-source, you might find it helpful to take a look at its source code.

The relevant aspects are:

const storage = require('uxp').storage;
const fs = storage.localFileSystem;

let data;

async function init() {
    let dataFolder = await fs.getDataFolder();
    try {
        let returnFile = await dataFolder.getEntry('storage.json');
        data = JSON.parse((await{format: storage.formats.utf8})).toString());
        return returnFile;
    } catch (e) {
        const file = await dataFolder.createEntry('storage.json', {type: storage.types.file, overwrite: true});
        if (file.isFile) {
            await file.write('{}', {append: false});
            data = {};
            return file;
        } else {
            throw new Error('Storage file storage.json was not a file.');

And then

const dataFile = await this.init();
data = JSON.parse((await{format: storage.formats.utf8})).toString());

for reading and

const dataFile = await this.init();
data[key] = value;
return await dataFile.write(JSON.stringify(data), {append: false, format: storage.formats.utf8})

for writing.

I hope this helps :slightly_smiling_face:


Awesome! Thanks @pklaschka, I’ll definitely make use of your library!


That’s a little confusing: you’re both setting the data global in init() and also showing recomputing it after And then.

1 Like

Yep, that’s a performance optimization that’s actually useful in the library, but not really for demonstrating how it works (which is why I left the optimization out of my answer; in the library, I don’t “re-read” the file when I already “know” its contents). I didn’t have the time to rewrite this code when I answered the question, so that’s why it’s in my answer :wink:

Yes, sorry, I should have said I was noting this not because the library code is wrong, but because the juxtaposition might confuse beginners…

1 Like

What is the option append: false used for? And what are the other options available? The Storage module API docs do not explain them.

1 Like

@pklaschka hey Pablo, your code doesn’t seem to work at all, no matter if the storage.json exists or not.

1 Like

That once upon a time was an option with which it was possible to append to a file’s content using UXP. It seems to be removed (at least from the docs) now, though :slightly_smiling_face:

@aldobsom Sorry, but I’ll need some more details in order to help :slightly_smiling_face:. What do you expect the code to do, what does it do, what doesn’t it do, what have you tried so far etc.

Generally speaking, the code I posted here was more of a reference on how it might be possible to do it, not a copy-and-paste example (my library does this storage, after all, and the code is just a pointer to the way the library does it). For example, when using the code outside a class (with a function init), this doesn’t exist, meaning this.init() becomes init() and so on. All in all, this isn’t a copy-and-pastable example.

If you want to store JSON-based data, I recommend (shameless advertisement of a free-to-use thing :wink: ) using the library instead of using my code posted here since the lib is maintained and therefore won’t break in the future. In other use-cases, the example code above is more about giving an idea on how to do it.

@pklaschka for example this code will not read the json file and if there is no such file it will not create a new one since file.isFile seems to break the plugin frozen

1 Like

I’m currently unable to test it myself, right now. I do know that the code of the actual library works (cf., as I use it in my plugins and have tested it earlier today. I’ll hopefully be able to test (and maybe correct) the code I’ve posted here in a few days and come back to you on it, but for now, I’ll have to leave it like this:

1 Like