简体   繁体   English

Node.js - FileSystem.writeFile 返回格式错误的 JSON

[英]Node.js - FileSystem.writeFile returning badly formatted JSON

So the premise here is a JavaScript script that, among other things, is supposed to maintain a little "dictionary" of sorts as a local JSON file, where some user-defined strings can be mapped to a key (a string) and serialized.所以这里的前提是一个 JavaScript 脚本,除其他外,它应该维护一个小“字典”作为本地 JSON 文件,其中一些用户定义的字符串可以映射到一个键(一个字符串)并序列化。 The script happens to already depend on Node.js and I'm not trying to run this in a browser anyway, which is why I'm using Node.js's FileSystem library.该脚本恰好已经依赖于Node.js的,我并不想在浏览器中运行反正这一点,这就是为什么我如何使用Node.js的文件系统库。 The problem is when I try to save a new definition to this dictionary, using the function below.问题是当我尝试使用下面的函数将新定义保存到这本词典时。

(Also note that, just because of how data is juggled in the wrapper function in which this function is called, arguments are passed as an array of strings, rather than just a simple "key" and "value" string. This is intentional.) (另请注意,仅仅因为在调用此函数的包装函数中如何处理数据,参数作为字符串数组传递,而不仅仅是简单的“键”和“值”字符串。这是有意的。 )

var sDictFile = "dict.json";

async function com_setdef(args){
    if (args.length > 1) {
        let sJSONKey = args[0];
        let sDef = args.slice(1).join(" ");

        fs.readFile(sDictFile, "utf8", (err, data) => {
            if (err) throw err;

            let pDict = JSON.parse(JSON.stringify(data));

            if (pDict.hasOwnProperty(sJSONKey)) { // this entry already exists in the dictionary, so just edit it
                let pRow = pDict.sJSONKey;

                if (pRow.locked == true) {
                    return "This dictionary entry is locked. Its definition cannot be changed unless it is unlocked, which can only be done by an admin.";
                } else {
                    pRow.def = sDef;
                    fs.writeFile(sDictFile, JSON.stringify(pDict, null, 2), err => {
                        if (err) throw err ;
                    });
                }   
            } else { // this entry doesn't exist yet, so create it from scratch
                let sJSONValue = {"def":sDef,"locked":false,"viewlocked":false};
                pDict[sJSONKey] = sJSONValue;
                fs.writeFile(sDictFile, JSON.stringify(pDict, null, 2), err => {
                    if (err) throw err ;
                });
                return "completed";
            }
        });
    }   
}

And just to give it some data to load to begin with, I put this in the othwerwise empty dict.json:只是为了给它一些要加载的数据,我把它放在其他空的 dict.json 中:

{
    "A": {
        "def": "the first letter in the alphabet",
        "locked": false,
        "viewlocked": false
    }
}

When this function is first called with the arguments com_setdef( ["cedar", "a", "species", "of", "tree"] ) , the resulting dict.json that had previously been empty now looks like this:当这个函数第一次使用参数com_setdef( ["cedar", "a", "species", "of", "tree"] )被调用时,之前为空的 dict.json 现在看起来像这样:

"{\r\n\t\"A\": {\r\n\t\t\"def\": \"the first letter in the alphabet\",\r\n\t\t\"locked\": false,\r\n\t\t\"viewlocked\": false\r\n\t}\r\n}"

So not only did it not save any of the new data, I also have no idea where all this other junk was coming from.所以它不仅没有保存任何新数据,我也不知道所有这些其他垃圾是从哪里来的。 The Node.js documentation for FileSystem.readFile says that if the encoding isn't specified, that the raw buffer is returned, so I suspected that's what this is, but even when UTF-8 is specified, it's still filling the JSON with a bunch of garbage I didn't explicitly pass to it. FileSystem.readFile 的 Node.js 文档说,如果没有指定编码,则返回原始缓冲区,所以我怀疑这就是这个,但即使指定了 UTF-8,它仍然用一个一堆我没有明确传递给它的垃圾。

There's some additional bad news - it never ends up returning the string "completed".还有一些额外的坏消息 - 它永远不会返回字符串“已完成”。 This whole function is called within an async wrapper function that awaits the string returned from this function so it can then compare the length of it and make sure it's > 0 with str.length > 0 .整个函数在等待从该函数返回的字符串的异步包装函数中调用,因此它可以比较它的长度并确保它 > 0 和str.length > 0 Instead, I get: (node:89944) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of undefined .相反,我得到: (node:89944) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of undefined All this makes it seem like fs.readFile, an async process according to the documentation, never actually terminates.所有这一切使它看起来像 fs.readFile,根据文档的异步进程,从未真正终止。 I think.我认为。

So I clearly don't know what I'm doing.所以我显然不知道我在做什么。 Why is the script failing so spectacularly to add a new line to the JSON file and save it?为什么脚本在向 JSON 文件中添加新行并保存时如此失败?

Your problem is that data which is returned from fs.readfile() is already a string.您的问题是从fs.readfile()返回的data已经是一个字符串。 So when you do JSON.parse(JSON.stringify(data)) - you're actually first stringifying a string, and then parsing a stringified string will give you a string (hence all these annoying \\r\\n ).因此,当您执行JSON.parse(JSON.stringify(data)) - 您实际上首先将字符串字符串化,然后解析字符串化的字符串会给您一个字符串(因此所有这些烦人的\\r\\n )。
A way to see it is to add in your code console.log(typeof pDict) which will print string .查看它的一种方法是在您的代码中添加console.log(typeof pDict)它将打印string

The solution: make sure your dict.json is a well-formatted JSON, and then change to JSON.parse(data) (ie without JSON.stringify() ).解决方案:确保您的dict.json是格式良好的 JSON,然后更改为JSON.parse(data) (即没有JSON.stringify() )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM