From 7326e1ab490aab2220b139460165be0bfbf04f36 Mon Sep 17 00:00:00 2001 From: Marcin Puc <5671049+tranzystorek-io@users.noreply.github.com> Date: Sun, 26 Jul 2020 21:51:33 +0200 Subject: [PATCH] fix(std/json): Add newline at the end of json files (#6885) --- std/fs/README.md | 8 ++++- std/fs/write_json.ts | 63 ++++++++++++++++++++------------------- std/fs/write_json_test.ts | 24 +++++++-------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/std/fs/README.md b/std/fs/README.md index aad81acee8..0b71b2b9d5 100644 --- a/std/fs/README.md +++ b/std/fs/README.md @@ -133,18 +133,24 @@ const foo = readJsonSync("./foo.json"); Writes an object to a JSON file. -**WriteJsonOptions** +#### WriteJsonOptions - replacer : An array of strings and numbers that acts as a approved list for selecting the object properties that will be stringified. - space : Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. +You can also specify options from `Deno.WriteFileOptions` to configure how the +file is written. + ```ts import { writeJson, writeJsonSync } from "https://deno.land/std/fs/mod.ts"; writeJson("./target.dat", { foo: "bar" }, { spaces: 2 }); // returns a promise writeJsonSync("./target.dat", { foo: "bar" }, { replacer: ["foo"] }); // void + +// appends to the file instead of rewriting +writeJsonSync("./target.dat", { foo: "bar" }, { append: true }); ``` ### walk diff --git a/std/fs/write_json.ts b/std/fs/write_json.ts index 015957bba5..46c33572a7 100644 --- a/std/fs/write_json.ts +++ b/std/fs/write_json.ts @@ -2,9 +2,28 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any type Replacer = (key: string, value: any) => any; -export interface WriteJsonOptions { - spaces?: number | string; +export interface WriteJsonOptions extends Deno.WriteFileOptions { replacer?: Array | Replacer; + spaces?: number | string; +} + +function serialize( + filePath: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + object: any, + options: WriteJsonOptions, +): string { + try { + const jsonString = JSON.stringify( + object, + options.replacer as string[], + options.spaces, + ); + return `${jsonString}\n`; + } catch (err) { + err.message = `${filePath}: ${err.message}`; + throw err; + } } /* Writes an object to a JSON file. */ @@ -14,20 +33,12 @@ export async function writeJson( object: any, options: WriteJsonOptions = {}, ): Promise { - let contentRaw = ""; - - try { - contentRaw = JSON.stringify( - object, - options.replacer as string[], - options.spaces, - ); - } catch (err) { - err.message = `${filePath}: ${err.message}`; - throw err; - } - - await Deno.writeFile(filePath, new TextEncoder().encode(contentRaw)); + const jsonString = serialize(filePath, object, options); + await Deno.writeTextFile(filePath, jsonString, { + append: options.append, + create: options.create, + mode: options.mode, + }); } /* Writes an object to a JSON file. */ @@ -37,18 +48,10 @@ export function writeJsonSync( object: any, options: WriteJsonOptions = {}, ): void { - let contentRaw = ""; - - try { - contentRaw = JSON.stringify( - object, - options.replacer as string[], - options.spaces, - ); - } catch (err) { - err.message = `${filePath}: ${err.message}`; - throw err; - } - - Deno.writeFileSync(filePath, new TextEncoder().encode(contentRaw)); + const jsonString = serialize(filePath, object, options); + Deno.writeTextFileSync(filePath, jsonString, { + append: options.append, + create: options.create, + mode: options.mode, + }); } diff --git a/std/fs/write_json_test.ts b/std/fs/write_json_test.ts index c22bd7bf16..3fb32ca161 100644 --- a/std/fs/write_json_test.ts +++ b/std/fs/write_json_test.ts @@ -25,7 +25,7 @@ Deno.test("writeJsonIfNotExists", async function (): Promise { await Deno.remove(notExistsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonIfExists", async function (): Promise { @@ -46,7 +46,7 @@ Deno.test("writeJsonIfExists", async function (): Promise { await Deno.remove(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonIfExistsAnInvalidJson", async function (): Promise { @@ -71,7 +71,7 @@ Deno.test("writeJsonIfExistsAnInvalidJson", async function (): Promise { await Deno.remove(existsInvalidJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonWithSpaces", async function (): Promise { @@ -93,7 +93,7 @@ Deno.test("writeJsonWithSpaces", async function (): Promise { await Deno.remove(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{\n "a": "1"\n}`); + assertEquals(new TextDecoder().decode(content), `{\n "a": "1"\n}\n`); }); Deno.test("writeJsonWithReplacer", async function (): Promise { @@ -121,7 +121,7 @@ Deno.test("writeJsonWithReplacer", async function (): Promise { await Deno.remove(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonSyncIfNotExists", function (): void { @@ -140,7 +140,7 @@ Deno.test("writeJsonSyncIfNotExists", function (): void { Deno.removeSync(notExistsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonSyncIfExists", function (): void { @@ -161,7 +161,7 @@ Deno.test("writeJsonSyncIfExists", function (): void { Deno.removeSync(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); Deno.test("writeJsonSyncIfExistsAnInvalidJson", function (): void { @@ -186,10 +186,10 @@ Deno.test("writeJsonSyncIfExistsAnInvalidJson", function (): void { Deno.removeSync(existsInvalidJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); }); -Deno.test("writeJsonWithSpaces", function (): void { +Deno.test("writeJsonSyncWithSpaces", function (): void { const existsJsonFile = path.join(testdataDir, "file_write_spaces_sync.json"); const invalidJsonContent = new TextEncoder().encode(); @@ -208,10 +208,10 @@ Deno.test("writeJsonWithSpaces", function (): void { Deno.removeSync(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{\n "a": "1"\n}`); + assertEquals(new TextDecoder().decode(content), `{\n "a": "1"\n}\n`); }); -Deno.test("writeJsonWithReplacer", function (): void { +Deno.test("writeJsonSyncWithReplacer", function (): void { const existsJsonFile = path.join( testdataDir, "file_write_replacer_sync.json", @@ -239,5 +239,5 @@ Deno.test("writeJsonWithReplacer", function (): void { Deno.removeSync(existsJsonFile); - assertEquals(new TextDecoder().decode(content), `{"a":"1"}`); + assertEquals(new TextDecoder().decode(content), `{"a":"1"}\n`); });