From 61ffa8466bbfa4ca8b13b442a3bd63ef9504a6da Mon Sep 17 00:00:00 2001
From: EuAndreh <eu@euandre.org>
Date: Wed, 30 Apr 2025 06:23:27 -0300
Subject: src/content/en/: Unpluralize collection names

---
 .../en/til/2021/08/11/js-bigint-reviver.adoc       | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 src/content/en/til/2021/08/11/js-bigint-reviver.adoc

(limited to 'src/content/en/til/2021/08/11/js-bigint-reviver.adoc')

diff --git a/src/content/en/til/2021/08/11/js-bigint-reviver.adoc b/src/content/en/til/2021/08/11/js-bigint-reviver.adoc
new file mode 100644
index 0000000..98ee79b
--- /dev/null
+++ b/src/content/en/til/2021/08/11/js-bigint-reviver.adoc
@@ -0,0 +1,89 @@
+= Encoding and decoding JavaScript BigInt values with reviver
+:updatedat: 2021-08-13
+
+:reviver-fn: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_the_reviver_parameter
+:bigint: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
+:json-rfc: https://datatracker.ietf.org/doc/html/rfc8259
+
+`JSON.parse()` accepts a second parameter: a {reviver-fn}[`reviver()` function].
+It is a function that can be used to transform the `JSON` values as they're
+being parsed.
+
+As it turns out, when combined with JavaScript's {bigint}[`BigInt`] type, you
+can parse and encode JavaScript `BigInt` numbers via JSON:
+
+[source,javascript]
+----
+const bigIntReviver = (_, value) =>
+    typeof value === "string" && value.match(/^-?[0-9]+n$/)
+        ? BigInt(value.slice(0, value.length - 1))
+        : value;
+----
+
+I chose to interpret strings that contains only numbers and an ending `n`
+suffix as `BigInt` values, similar to how JavaScript interprets `123` (a number)
+differently from `123n` (a `bigint`);
+
+We do those checks before constructing the `BigInt` to avoid throwing needless
+exceptions and catching them on the parsing function, as this could easily
+become a bottleneck when parsing large JSON values.
+
+In order to do the full roundtrip, we now only need the `toJSON()` counterpart:
+
+[source,javascript]
+----
+BigInt.prototype.toJSON = function() {
+    return this.toString() + "n";
+};
+----
+
+With both `bigIntReviver` and `toJSON` defined, we can now successfully parse
+and encode JavaScript objects with `BigInt` values transparently:
+
+[source,javascript]
+----
+const s = `[
+    null,
+    true,
+    false,
+    -1,
+    3.14,
+    "a string",
+    { "a-number": "-123" },
+    { "a-bigint": "-123n" }
+]`;
+
+const parsed = JSON.parse(s, bigIntReviver);
+const s2 = JSON.stringify(parsed);
+
+console.log(parsed);
+console.log(s2);
+
+console.log(typeof parsed[6]["a-number"])
+console.log(typeof parsed[7]["a-bigint"])
+----
+
+The output of the above is:
+
+[source,javascript]
+----
+[
+  null,
+  true,
+  false,
+  -1,
+  3.14,
+  'a string',
+  { 'a-number': '-123' },
+  { 'a-bigint': -123n }
+]
+[null,true,false,-1,3.14,"a string",{"a-number":"-123"},{"a-bigint":"-123n"}]
+string
+bigint
+----
+
+If you're on a web browser, you can probably try copying and pasting the above
+code on the console right now, as is.
+
+Even though {json-rfc}[`JSON`] doesn't include `BigInt` number, encoding and
+decoding them as strings is quite trivial on JavaScript.
-- 
cgit v1.2.3

