From 2c297cac675b9b398a59eb39dfc210fbdc6e556f Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sun, 26 Feb 2023 22:12:29 +0100 Subject: [PATCH 01/19] add doc strings for json module --- src/Core__JSON.resi | 518 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 509 insertions(+), 9 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index fc086a01..7194c0ec 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -1,29 +1,371 @@ +/*** + Functions for interacting with JSON. +*/ + +/** +A type representing a JSON object. +*/ type t = Js.Json.t +/** +A type which describes how the value should be transformed while parsing. +It is a function which receives a key and a value. +*/ type jsonReviver external asJsonReviver: 'a => jsonReviver = "%identity" + +/** +A type which describes how the value should be transformed while stringification. +It is a function which receives a key and a value. +*/ type jsonReplacer external asJsonReplacer: 'a => jsonReplacer = "%identity" -@val external parseExn: string => t = "JSON.parse" -@val external parseExnWithReviver: (string, jsonReviver) => t = "JSON.parse" -@val external stringify: t => string = "JSON.stringify" -@val external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" -@val external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" -@val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" +/** +`parseExn(string)` + +Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. +It returns a JSON type. If you want to get any type, use `JSON.parseToAnyExn` instead. + +## Examples +```rescript +try { + JSON.parseExn(`{"foo":"bar","hello":"world"}`) + // { foo: 'bar', hello: 'world' } + + JSON.parseExn("") + // error +} catch { +| Js.Exn.Error(obj) => Console.log("error") +} +``` +*/ +@raises +@val +external parseExn: string => t = "JSON.parse" + +/** +`parseExnWithReviver(string, jsonReviver)` + +Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. +The reviver describes how the value should be transformed. It is a function which receives a key and a value. +It returns a JSON type. If you want to get any type, use `JSON.parseToAnyExnWithReviver` instead. + +## Examples +```rescript +let reviver = JSON.asJsonReviver((key, value) => { + if key->String.toLowerCase->String.includes("date") { + Date.fromString(value)->Obj.magic + } else { + value + } +}) + +let jsonString = `{"parseAsDate":"2023-02-26","parseAsString":"2023-02-26"}` + +try { + JSON.parseExnWithReviver(jsonString, reviver) + // { parseAsDate: 2023-02-26T00:00:00.000Z, parseAsString: '2023-02-26' } + + JSON.parseExnWithReviver("", reviver) + // error +} catch { +| Js.Exn.Error(_) => Console.log("error") +} +``` +*/ +@raises +@val +external parseExnWithReviver: (string, jsonReviver) => t = "JSON.parse" + +/** +`stringify(json)` + +Converts a JSON object to a JSON string. +If you want to stringify any type, use `JSON.stringifyAny` instead. + +## Examples +```rescript +Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) +->JSON.Encode.object +->JSON.stringify +// {"foo":"bar","hello":"world"} +} +``` +*/ +@val +external stringify: t => string = "JSON.stringify" + +/** +`stringifyWithIndent(json, indentation)` + +Converts a JSON object to a JSON string. The output will be indented. +If you want to stringify any type, use `JSON.stringifyAnyWithIndent` instead. + +## Examples +```rescript +Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) +->JSON.Encode.object +->JSON.stringify +// { +// "foo": "bar", +// "hello": "world" +// } +} +``` +*/ +@val +external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" + +/** +`stringifyWithReplacer(json, jsonReplacer)` + +Converts a JSON object to a JSON string. +The replacer describes how the value should be transformed. It is a function which receives a key and a value. +If you want to stringify any type, use `JSON.stringifyAnyWithReplacer` instead. + +## Examples +```rescript +let replacer = JSON.asJsonReplacer((key, value) => { + if key === "foo" { + String.toUpperCase(value) + } else if value === "world" { + value ++ "!" + } else { + value + } +}) -@val external parseToAnyExn: string => 'a = "JSON.parse" -@val external parseToAnyExnWithReviver: (string, jsonReviver) => 'a = "JSON.parse" -@val external stringifyAny: 'a => option = "JSON.stringify" +Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) +->JSON.Encode.object +->JSON.stringifyWithReplacer(replacer) +// {"foo":"BAR","hello":"world!"} +``` +*/ +@val +external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" + +/** +`stringifyWithReplacerAndIndent(json, jsonReplacer, indentation)` + +Converts a JSON object to a JSON string. The output will be indented. +The replacer describes how the value should be transformed. It is a function which receives a key and a value. + +## Examples +```rescript +let replacer = JSON.asJsonReplacer((key, value) => { + if key === "foo" { + String.toUpperCase(value) + } else if value === "world" { + value ++ "!" + } else { + value + } +}) + +Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) +->JSON.Encode.object +->JSON.stringifyWithReplacerAndIndent(replacer, 2) +// { +// "foo": "BAR", +// "hello": "world!" +// } +``` +*/ +@val +external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" + +/** +`parseToAnyExn(string)` + +Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. +It returns any type. If you want to get a JSON type, use `JSON.parseExn` instead. + +## Examples +```rescript +try { + JSON.parseToAnyExn(`{"foo":"bar","hello":"world"}`) + // { foo: 'bar', hello: 'world' } + + JSON.parseExn("") + // error +} catch { +| Js.Exn.Error(obj) => Console.log("error") +} +``` +*/ +@raises +@val +external parseToAnyExn: string => 'a = "JSON.parse" + +/** +`parseToAnyExnWithReviver(string, jsonReviver)` + +Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. +The reviver describes how the value should be transformed. It is a function which receives a key and a value. +It returns any type. If you want to get a JSON type, use `JSON.parseExnWithReviver` instead. + +## Examples +```rescript +let reviver = JSON.asJsonReviver((key, value) => { + if key->String.toLowerCase->String.includes("date") { + Date.fromString(value)->Obj.magic + } else { + value + } +}) + +let jsonString = `{"parseAsDate":"2023-02-26","parseAsString":"2023-02-26"}` + +try { + JSON.parseToAnyExnWithReviver(jsonString, reviver) + // { parseAsDate: 2023-02-26T00:00:00.000Z, parseAsString: '2023-02-26' } + + JSON.parseToAnyExnWithReviver("", reviver) + // error +} catch { +| Js.Exn.Error(_) => Console.log("error") +} +``` +*/ +@raises +@val +external parseToAnyExnWithReviver: (string, jsonReviver) => 'a = "JSON.parse" + +/** +`stringifyAny(any)` + +Converts any type to a JSON string. Values which can't be strinfified will return `None`. +Throws a JavaScript exception (TypeError), if the value can't be stringified. +If you want to stringify a JSON object, use `JSON.stringify` instead. + +## Examples +```rescript +Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAny +// Some({"foo":"bar","hello":"world"}) + +let someFunction = () => {"hello world"} + +someFunction->JSON.stringifyAny +// None + +BigInt.fromInt(0)->JSON.stringifyAny +// exception +``` +*/ +@raises +@val +external stringifyAny: 'a => option = "JSON.stringify" + +/** +`stringifyAnyWithIndent(any, indentation)` + +Converts any type to a JSON string. Values which can't be strinfified will return `None`. +Throws a JavaScript exception (TypeError), if the value can't be stringified. +If you want to stringify a JSON object, use `JSON.stringifyWithIndent` instead. + +## Examples +```rescript +Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAnyWithIndent(2) +// Some({ +// "foo": "bar", +// "hello": "world" +// }) + +let someFunction = () => {"hello world"} + +someFunction->JSON.stringifyAnyWithIndent(2) +// None + +BigInt.fromInt(0)->JSON.stringifyAnyWithIndent(2) +// exception +``` +*/ +@raises @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" + +/** +`stringifyAnyWithReplacer(json, jsonReplacer)` + +Converts any type to a JSON string. Values which can't be strinfified will return `None`. +The replacer describes how the value should be transformed. It is a function which receives a key and a value. +Throws a JavaScript exception (TypeError), if the value can't be stringified. +If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. + +## Examples +```rescript +let replacer = JSON.asJsonReplacer((key, value) => { + if key === "foo" { + String.toUpperCase(value) + } else if value === "world" { + value ++ "!" + } else { + value + } +}) + +Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAnyWithReplacer(replacer) +// Some({"foo":"BAR","hello":"world!"}) + +let someFunction = () => {"hello world"} + +someFunction->JSON.stringifyAnyWithReplacer(replacer) +// None + +BigInt.fromInt(0)->JSON.stringifyAnyWithReplacer(replacer) +// exception +``` +*/ +@raises @val external stringifyAnyWithReplacer: ('a, jsonReplacer) => option = "JSON.stringify" + +/** +`stringifyAnyWithReplacerAndIndent(json, jsonReplacer, indentation)` + +Converts any type to a JSON string. The output will be indented. Values which can't be strinfified will return `None`. +The replacer describes how the value should be transformed. It is a function which receives a key and a value. +Throws a JavaScript exception (TypeError), if the value can't be stringified. +If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. + +## Examples +```rescript +let replacer = JSON.asJsonReplacer((key, value) => { + if key === "foo" { + String.toUpperCase(value) + } else if value === "world" { + value ++ "!" + } else { + value + } +}) + +Dict.fromArray([("foo", "bar"), ("hello", "world")]) +->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +// Some({ +// "foo": "BAR", +// "hello": "world!" +// }) + +let someFunction = () => {"hello world"} + +someFunction->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +// None + +BigInt.fromInt(0)->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +// exception +``` +*/ +@raises @val external stringifyAnyWithReplacerAndIndent: ('a, jsonReplacer, int) => option = "JSON.stringify" module Classify: { + /** + A type representing a JavaScript type. + */ type t = | Bool(bool) | Null @@ -32,24 +374,182 @@ module Classify: { | Object(Core__Dict.t) | Array(array) + /** + Returns the JavaScript type of any value. + + ## Examples + ```rescript + JSON.Classify.classify("hello world") + // String("hello world") + + JSON.Classify.classify(42) + // Number(42) + ``` + */ let classify: 'a => t } module Encode: { + /** + Returns a boolean as a JSON object. + + ## Examples + ```rescript + JSON.Encode.bool(true) + ``` + */ external bool: bool => t = "%identity" + + /** + Returns null as a JSON object. + + ## Examples + ```rescript + JSON.Encode.null + ``` + */ external null: t = "#null" + + /** + Returns a string as a JSON object. + + ## Examples + ```rescript + JSON.Encode.string("hello world") + ``` + */ external string: string => t = "%identity" + + /** + Returns an int as a JSON object. + + ## Examples + ```rescript + JSON.Encode.int(42) + ``` + */ external int: int => t = "%identity" + + /** + Returns a float as a JSON object. + + ## Examples + ```rescript + JSON.Encode.float(42.0) + ``` + */ external float: float => t = "%identity" + + /** + Returns a dict as a JSON object. + + ## Examples + ```rescript + let dict = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ]) + + JSON.Encode.object(dict) + ``` + */ external object: Core__Dict.t => t = "%identity" + + /** + Returns an array as a JSON object. + + ## Examples + ```rescript + let array = [JSON.Encode.string("hello world"), JSON.Encode.int(42)] + + JSON.Encode.array(array) + ``` + */ external array: array => t = "%identity" } module Decode: { + /** + Decodes a single JSON value. If the value is a bool, it will return `Some(bool)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`true`)->JSON.Decode.bool + // Some(true) + + JSON.parseExn(`"hello world"`)->JSON.Decode.bool + // None + ``` + */ let bool: t => option + + /** + Decodes a single JSON value. If the value is null, it will return `Some(Null.t)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`null`)->JSON.Decode.null + // Some(null) + + JSON.parseExn(`"hello world"`)->JSON.Decode.null + // None + ``` + */ let null: t => option> + + /** + Decodes a single JSON value. If the value is a string, it will return `Some(string)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`"hello world"`)->JSON.Decode.string + // Some("hello world") + + JSON.parseExn(`42`)->JSON.Decode.string + // None + ``` + */ let string: t => option + + /** + Decodes a single JSON value. If the value is a float, it will return `Some(float)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`42.0`)->JSON.Decode.float + // Some(42.0) + + JSON.parseExn(`"hello world"`)->JSON.Decode.float + // None + ``` + */ let float: t => option + + /** + Decodes a single JSON value. If the value is an object, it will return `Some(Dict.t)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`{"foo":"bar"}`)->JSON.Decode.object + // Some({ foo: 'bar' }) + + JSON.parseExn(`"hello world"`)->JSON.Decode.object + // None + ``` + */ let object: t => option> + + /** + Decodes a single JSON value. If the value is an array, it will return `Some(array)` - otherwise it will return `None`. + + ## Examples + ```rescript + JSON.parseExn(`["foo", "bar"]`)->JSON.Decode.array + // Some([ 'foo', 'bar' ]) + + JSON.parseExn(`"hello world"`)->JSON.Decode.array + // None + ``` + */ let array: t => option> } From 7e733b1a6f564b76ee58de1f8006cd444482f166 Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 09:34:24 +0100 Subject: [PATCH 02/19] changed type of the reviver function --- src/Core__JSON.res | 7 +++---- src/Core__JSON.resi | 29 ++++++++++++++++------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index 100ae5ee..81208c17 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -1,19 +1,17 @@ type t = Js.Json.t -type jsonReviver -external asJsonReviver: 'a => jsonReviver = "%identity" type jsonReplacer external asJsonReplacer: 'a => jsonReplacer = "%identity" @val external parseExn: string => t = "JSON.parse" -@val external parseExnWithReviver: (string, jsonReviver) => t = "JSON.parse" +@val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" @val external stringify: t => string = "JSON.stringify" @val external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" @val external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" @val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" @val external parseToAnyExn: string => 'a = "JSON.parse" -@val external parseToAnyExnWithReviver: (string, jsonReviver) => 'a = "JSON.parse" +@val external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" @val external stringifyAny: 'a => option = "JSON.stringify" @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" @@ -59,6 +57,7 @@ module Encode = { external float: float => t = "%identity" external object: Core__Dict.t => t = "%identity" external array: array => t = "%identity" + external any: 'a => t = "%identity" } module Decode = { diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 7194c0ec..a0f0334a 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -7,13 +7,6 @@ A type representing a JSON object. */ type t = Js.Json.t -/** -A type which describes how the value should be transformed while parsing. -It is a function which receives a key and a value. -*/ -type jsonReviver -external asJsonReviver: 'a => jsonReviver = "%identity" - /** A type which describes how the value should be transformed while stringification. It is a function which receives a key and a value. @@ -45,7 +38,7 @@ try { external parseExn: string => t = "JSON.parse" /** -`parseExnWithReviver(string, jsonReviver)` +`parseExnWithReviver(string, reviver)` Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. The reviver describes how the value should be transformed. It is a function which receives a key and a value. @@ -53,13 +46,13 @@ It returns a JSON type. If you want to get any type, use `JSON.parseToAnyExnWith ## Examples ```rescript -let reviver = JSON.asJsonReviver((key, value) => { +let reviver = (key, value) => { if key->String.toLowerCase->String.includes("date") { - Date.fromString(value)->Obj.magic + value->JSON.Decode.string->Option.map(Date.fromString)->JSON.Encode.any } else { value } -}) +} let jsonString = `{"parseAsDate":"2023-02-26","parseAsString":"2023-02-26"}` @@ -76,7 +69,7 @@ try { */ @raises @val -external parseExnWithReviver: (string, jsonReviver) => t = "JSON.parse" +external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" /** `stringify(json)` @@ -230,7 +223,7 @@ try { */ @raises @val -external parseToAnyExnWithReviver: (string, jsonReviver) => 'a = "JSON.parse" +external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" /** `stringifyAny(any)` @@ -466,6 +459,16 @@ module Encode: { ``` */ external array: array => t = "%identity" + + /** + Returns any as a JSON object. + + ## Examples + ```rescript + JSON.Encode.any("test") + ``` + */ + external any: 'a => t = "%identity" } module Decode: { From 27a454c590c4d2c701e92ea40b96311fa39c7fe0 Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 09:35:02 +0100 Subject: [PATCH 03/19] add @raises annotation also in res file --- src/Core__JSON.res | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index 81208c17..61df7113 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -3,21 +3,21 @@ type t = Js.Json.t type jsonReplacer external asJsonReplacer: 'a => jsonReplacer = "%identity" -@val external parseExn: string => t = "JSON.parse" -@val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" +@raises @val external parseExn: string => t = "JSON.parse" +@raises @val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" @val external stringify: t => string = "JSON.stringify" @val external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" @val external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" @val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" -@val external parseToAnyExn: string => 'a = "JSON.parse" -@val external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" -@val external stringifyAny: 'a => option = "JSON.stringify" -@val +@raises @val external parseToAnyExn: string => 'a = "JSON.parse" +@raises @val external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" +@raises @val external stringifyAny: 'a => option = "JSON.stringify" +@raises @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" -@val +@raises @val external stringifyAnyWithReplacer: ('a, jsonReplacer) => option = "JSON.stringify" -@val +@raises @val external stringifyAnyWithReplacerAndIndent: ('a, jsonReplacer, int) => option = "JSON.stringify" From ae8c1a6065c622b3899f597f426f21c526cddb18 Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 09:37:42 +0100 Subject: [PATCH 04/19] remove parseToAnyExn and parseToAnyExnWithReviver --- src/Core__JSON.res | 2 -- src/Core__JSON.resi | 61 ++------------------------------------------- 2 files changed, 2 insertions(+), 61 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index 61df7113..8608ee7e 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -10,8 +10,6 @@ external asJsonReplacer: 'a => jsonReplacer = "%identity" @val external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" @val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" -@raises @val external parseToAnyExn: string => 'a = "JSON.parse" -@raises @val external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" @raises @val external stringifyAny: 'a => option = "JSON.stringify" @raises @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index a0f0334a..4285b856 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -18,7 +18,7 @@ external asJsonReplacer: 'a => jsonReplacer = "%identity" `parseExn(string)` Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. -It returns a JSON type. If you want to get any type, use `JSON.parseToAnyExn` instead. +It returns a JSON type. ## Examples ```rescript @@ -42,7 +42,7 @@ external parseExn: string => t = "JSON.parse" Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. The reviver describes how the value should be transformed. It is a function which receives a key and a value. -It returns a JSON type. If you want to get any type, use `JSON.parseToAnyExnWithReviver` instead. +It returns a JSON type. ## Examples ```rescript @@ -168,63 +168,6 @@ Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string @val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" -/** -`parseToAnyExn(string)` - -Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. -It returns any type. If you want to get a JSON type, use `JSON.parseExn` instead. - -## Examples -```rescript -try { - JSON.parseToAnyExn(`{"foo":"bar","hello":"world"}`) - // { foo: 'bar', hello: 'world' } - - JSON.parseExn("") - // error -} catch { -| Js.Exn.Error(obj) => Console.log("error") -} -``` -*/ -@raises -@val -external parseToAnyExn: string => 'a = "JSON.parse" - -/** -`parseToAnyExnWithReviver(string, jsonReviver)` - -Parses a JSON string or throws a JavaScript exception (SyntaxError), if the string isn't valid. -The reviver describes how the value should be transformed. It is a function which receives a key and a value. -It returns any type. If you want to get a JSON type, use `JSON.parseExnWithReviver` instead. - -## Examples -```rescript -let reviver = JSON.asJsonReviver((key, value) => { - if key->String.toLowerCase->String.includes("date") { - Date.fromString(value)->Obj.magic - } else { - value - } -}) - -let jsonString = `{"parseAsDate":"2023-02-26","parseAsString":"2023-02-26"}` - -try { - JSON.parseToAnyExnWithReviver(jsonString, reviver) - // { parseAsDate: 2023-02-26T00:00:00.000Z, parseAsString: '2023-02-26' } - - JSON.parseToAnyExnWithReviver("", reviver) - // error -} catch { -| Js.Exn.Error(_) => Console.log("error") -} -``` -*/ -@raises -@val -external parseToAnyExnWithReviver: (string, (string, t) => t) => 'a = "JSON.parse" - /** `stringifyAny(any)` From 34aedd6a6e3624bfbb1a6de5d1baab9ec3e679ec Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 10:14:53 +0100 Subject: [PATCH 05/19] change type of replacer --- src/Core__JSON.res | 13 +-- src/Core__JSON.resi | 232 +++++++++++++++++++++++++------------------- 2 files changed, 135 insertions(+), 110 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index 8608ee7e..d1d0b3ef 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -1,22 +1,19 @@ type t = Js.Json.t -type jsonReplacer -external asJsonReplacer: 'a => jsonReplacer = "%identity" - @raises @val external parseExn: string => t = "JSON.parse" @raises @val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" @val external stringify: t => string = "JSON.stringify" @val external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" -@val external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" -@val external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" - +@val external stringifyWithReplacer: (t, (string, t) => t) => string = "JSON.stringify" +@val +external stringifyWithReplacerAndIndent: (t, (string, t) => t, int) => string = "JSON.stringify" @raises @val external stringifyAny: 'a => option = "JSON.stringify" @raises @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" @raises @val -external stringifyAnyWithReplacer: ('a, jsonReplacer) => option = "JSON.stringify" +external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "JSON.stringify" @raises @val -external stringifyAnyWithReplacerAndIndent: ('a, jsonReplacer, int) => option = +external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => option = "JSON.stringify" module Classify = { diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 4285b856..6b4cb5ed 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -7,13 +7,6 @@ A type representing a JSON object. */ type t = Js.Json.t -/** -A type which describes how the value should be transformed while stringification. -It is a function which receives a key and a value. -*/ -type jsonReplacer -external asJsonReplacer: 'a => jsonReplacer = "%identity" - /** `parseExn(string)` @@ -79,11 +72,15 @@ If you want to stringify any type, use `JSON.stringifyAny` instead. ## Examples ```rescript -Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) -->JSON.Encode.object -->JSON.stringify -// {"foo":"bar","hello":"world"} -} +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +JSON.stringify(json) +// {"foo":"bar","hello":"world","someNumber":42} ``` */ @val @@ -97,21 +94,26 @@ If you want to stringify any type, use `JSON.stringifyAnyWithIndent` instead. ## Examples ```rescript -Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) -->JSON.Encode.object -->JSON.stringify +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +JSON.stringifyWithIndent(json, 2) // { // "foo": "bar", -// "hello": "world" +// "hello": "world", +// "someNumber": 42 // } -} ``` */ @val external stringifyWithIndent: (t, @as(json`null`) _, int) => string = "JSON.stringify" /** -`stringifyWithReplacer(json, jsonReplacer)` +`stringifyWithReplacer(json, replacer)` Converts a JSON object to a JSON string. The replacer describes how the value should be transformed. It is a function which receives a key and a value. @@ -119,70 +121,84 @@ If you want to stringify any type, use `JSON.stringifyAnyWithReplacer` instead. ## Examples ```rescript -let replacer = JSON.asJsonReplacer((key, value) => { - if key === "foo" { - String.toUpperCase(value) - } else if value === "world" { - value ++ "!" - } else { - value +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +let replacer = (key, value) => { + let decodedValue = value->JSON.Decode.string + + switch decodedValue { + | Some(string) => string->String.toUpperCase->JSON.Encode.string + | None => value } -}) +} -Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) -->JSON.Encode.object -->JSON.stringifyWithReplacer(replacer) -// {"foo":"BAR","hello":"world!"} +JSON.stringifyWithReplacer(json, replacer) +// {"foo":"BAR","hello":"WORLD","someNumber":42} ``` */ @val -external stringifyWithReplacer: (t, jsonReplacer) => string = "JSON.stringify" +external stringifyWithReplacer: (t, (string, t) => t) => string = "JSON.stringify" /** -`stringifyWithReplacerAndIndent(json, jsonReplacer, indentation)` +`stringifyWithReplacerAndIndent(json, replacer, indentation)` Converts a JSON object to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. ## Examples ```rescript -let replacer = JSON.asJsonReplacer((key, value) => { - if key === "foo" { - String.toUpperCase(value) - } else if value === "world" { - value ++ "!" - } else { - value +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +let replacer = (key, value) => { + let decodedValue = value->JSON.Decode.string + + switch decodedValue { + | Some(string) => string->String.toUpperCase->JSON.Encode.string + | None => value } -}) +} -Dict.fromArray([("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world"))]) -->JSON.Encode.object -->JSON.stringifyWithReplacerAndIndent(replacer, 2) +JSON.stringifyWithReplacerAndIndent(json, replacer, 2) // { -// "foo": "BAR", -// "hello": "world!" -// } + "foo": "BAR", + "hello": "WORLD", + "someNumber": 42 +} ``` */ @val -external stringifyWithReplacerAndIndent: (t, jsonReplacer, int) => string = "JSON.stringify" +external stringifyWithReplacerAndIndent: (t, (string, t) => t, int) => string = "JSON.stringify" /** `stringifyAny(any)` -Converts any type to a JSON string. Values which can't be strinfified will return `None`. -Throws a JavaScript exception (TypeError), if the value can't be stringified. +Converts any type to a JSON string. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringify` instead. ## Examples ```rescript -Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAny -// Some({"foo":"bar","hello":"world"}) +let json = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) -let someFunction = () => {"hello world"} +JSON.stringifyAny(json) +// {"foo":"bar","hello":"world","someNumber":42} -someFunction->JSON.stringifyAny +JSON.stringifyAny(() => "hello world") // None BigInt.fromInt(0)->JSON.stringifyAny @@ -196,24 +212,30 @@ external stringifyAny: 'a => option = "JSON.stringify" /** `stringifyAnyWithIndent(any, indentation)` -Converts any type to a JSON string. Values which can't be strinfified will return `None`. -Throws a JavaScript exception (TypeError), if the value can't be stringified. +Converts any type to a JSON string. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithIndent` instead. ## Examples ```rescript -Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAnyWithIndent(2) -// Some({ -// "foo": "bar", -// "hello": "world" -// }) +let json = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) -let someFunction = () => {"hello world"} +JSON.stringifyAnyWithIndent(json, 2) +// { +// "foo": "bar", +// "hello": "world", +// "someNumber": 42 +// } -someFunction->JSON.stringifyAnyWithIndent(2) +JSON.stringifyAny(() => "hello world") // None -BigInt.fromInt(0)->JSON.stringifyAnyWithIndent(2) +BigInt.fromInt(0)->JSON.stringifyAny // exception ``` */ @@ -222,80 +244,86 @@ BigInt.fromInt(0)->JSON.stringifyAnyWithIndent(2) external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" /** -`stringifyAnyWithReplacer(json, jsonReplacer)` +`stringifyAnyWithReplacer(json, replacer)` -Converts any type to a JSON string. Values which can't be strinfified will return `None`. -The replacer describes how the value should be transformed. It is a function which receives a key and a value. -Throws a JavaScript exception (TypeError), if the value can't be stringified. +Converts any type to a JSON string. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. ## Examples ```rescript -let replacer = JSON.asJsonReplacer((key, value) => { - if key === "foo" { - String.toUpperCase(value) - } else if value === "world" { - value ++ "!" - } else { - value +let json = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) + +let replacer = (key, value) => { + let decodedValue = value->JSON.Decode.string + + switch decodedValue { + | Some(string) => string->String.toUpperCase->JSON.Encode.string + | None => value } -}) - -Dict.fromArray([("foo", "bar"), ("hello", "world")])->JSON.stringifyAnyWithReplacer(replacer) -// Some({"foo":"BAR","hello":"world!"}) +} -let someFunction = () => {"hello world"} +JSON.stringifyAnyWithReplacer(json, replacer) +// {"foo":"BAR","hello":"WORLD","someNumber":42} -someFunction->JSON.stringifyAnyWithReplacer(replacer) +JSON.stringifyAny(() => "hello world") // None -BigInt.fromInt(0)->JSON.stringifyAnyWithReplacer(replacer) +BigInt.fromInt(0)->JSON.stringifyAny // exception ``` */ @raises @val -external stringifyAnyWithReplacer: ('a, jsonReplacer) => option = "JSON.stringify" +external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "JSON.stringify" /** -`stringifyAnyWithReplacerAndIndent(json, jsonReplacer, indentation)` +`stringifyAnyWithReplacerAndIndent(json, replacer, indentation)` -Converts any type to a JSON string. The output will be indented. Values which can't be strinfified will return `None`. +Converts any type to a JSON string. Values which can't be strinfified will return `None`. The replacer describes how the value should be transformed. It is a function which receives a key and a value. Throws a JavaScript exception (TypeError), if the value can't be stringified. If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. ## Examples ```rescript -let replacer = JSON.asJsonReplacer((key, value) => { - if key === "foo" { - String.toUpperCase(value) - } else if value === "world" { - value ++ "!" - } else { - value +let json = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) + +let replacer = (key, value) => { + let decodedValue = value->JSON.Decode.string + + switch decodedValue { + | Some(string) => string->String.toUpperCase->JSON.Encode.string + | None => value } -}) +} -Dict.fromArray([("foo", "bar"), ("hello", "world")]) -->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) -// Some({ +JSON.stringifyAnyWithReplacerAndIndent(json, replacer, 2) +// { // "foo": "BAR", -// "hello": "world!" -// }) - -let someFunction = () => {"hello world"} +// "hello": "WORLD", +// "someNumber": 42 +// } -someFunction->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +JSON.stringifyAny(() => "hello world") // None -BigInt.fromInt(0)->JSON.stringifyAnyWithReplacerAndIndent(replacer, 2) +BigInt.fromInt(0)->JSON.stringifyAny // exception ``` */ @raises @val -external stringifyAnyWithReplacerAndIndent: ('a, jsonReplacer, int) => option = +external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => option = "JSON.stringify" module Classify: { From 5687b8cd6aad38534ab3be3a8014de7934c9600d Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 10:40:44 +0100 Subject: [PATCH 06/19] add stringifyWithFilter functions --- src/Core__JSON.res | 5 ++ src/Core__JSON.resi | 135 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 128 insertions(+), 12 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index d1d0b3ef..08776895 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -7,6 +7,8 @@ type t = Js.Json.t @val external stringifyWithReplacer: (t, (string, t) => t) => string = "JSON.stringify" @val external stringifyWithReplacerAndIndent: (t, (string, t) => t, int) => string = "JSON.stringify" +@val external stringifyWithFilter: (t, array) => string = "JSON.stringify" +@val external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON.stringify" @raises @val external stringifyAny: 'a => option = "JSON.stringify" @raises @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" @@ -15,6 +17,9 @@ external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "J @raises @val external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => option = "JSON.stringify" +@raises @val external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify" +@raises @val +external stringifyAnyWithFilterAndIndent: ('a, array, int) => string = "JSON.stringify" module Classify = { type t = diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 6b4cb5ed..35c2d43b 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -149,6 +149,7 @@ external stringifyWithReplacer: (t, (string, t) => t) => string = "JSON.stringif Converts a JSON object to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. +If you want to stringify any type, use `JSON.stringifyAnyWithReplacerAndIndent` instead. ## Examples ```rescript @@ -179,6 +180,53 @@ JSON.stringifyWithReplacerAndIndent(json, replacer, 2) @val external stringifyWithReplacerAndIndent: (t, (string, t) => t, int) => string = "JSON.stringify" +/** +`stringifyWithFilter(json, filter)` + +Converts a JSON object to a JSON string. +The filter is an array of keys, which should be included in the output. +If you want to stringify any type, use `JSON.stringifyAnyWithFilter` instead. + +## Examples +```rescript +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +JSON.stringifyWithFilter(json, ["foo", "someNumber"]) +// {"foo":"bar","someNumber":42} +``` +*/ +@val external stringifyWithFilter: (t, array) => string = "JSON.stringify" + +/** +`stringifyWithFilterAndIndent(json, filter, indentation)` + +Converts a JSON object to a JSON string. The output will be indented. +The filter is an array of keys, which should be included in the output. +If you want to stringify any type, use `JSON.stringifyAnyWithFilterAndIndent` instead. + +## Examples +```rescript +let json = + Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), + ])->JSON.Encode.object + +JSON.stringifyWithFilterAndIndent(json, ["foo", "someNumber"], 2) +// { +// "foo": "bar", +// "someNumber": 42 +// } +``` +*/ +@val external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON.stringify" + /** `stringifyAny(any)` @@ -189,13 +237,13 @@ If you want to stringify a JSON object, use `JSON.stringify` instead. ## Examples ```rescript -let json = Dict.fromArray([ +let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world")), ("someNumber", JSON.Encode.int(42)), ]) -JSON.stringifyAny(json) +JSON.stringifyAny(dict) // {"foo":"bar","hello":"world","someNumber":42} JSON.stringifyAny(() => "hello world") @@ -212,20 +260,20 @@ external stringifyAny: 'a => option = "JSON.stringify" /** `stringifyAnyWithIndent(any, indentation)` -Converts any type to a JSON string. +Converts any type to a JSON string. The output will be indented. Stringifing a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithIndent` instead. ## Examples ```rescript -let json = Dict.fromArray([ +let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world")), ("someNumber", JSON.Encode.int(42)), ]) -JSON.stringifyAnyWithIndent(json, 2) +JSON.stringifyAnyWithIndent(dict, 2) // { // "foo": "bar", // "hello": "world", @@ -247,13 +295,14 @@ external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option `stringifyAnyWithReplacer(json, replacer)` Converts any type to a JSON string. +The replacer describes how the value should be transformed. It is a function which receives a key and a value. Stringifing a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. ## Examples ```rescript -let json = Dict.fromArray([ +let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world")), ("someNumber", JSON.Encode.int(42)), @@ -268,7 +317,7 @@ let replacer = (key, value) => { } } -JSON.stringifyAnyWithReplacer(json, replacer) +JSON.stringifyAnyWithReplacer(dict, replacer) // {"foo":"BAR","hello":"WORLD","someNumber":42} JSON.stringifyAny(() => "hello world") @@ -285,14 +334,15 @@ external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "J /** `stringifyAnyWithReplacerAndIndent(json, replacer, indentation)` -Converts any type to a JSON string. Values which can't be strinfified will return `None`. +Converts any type to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. -Throws a JavaScript exception (TypeError), if the value can't be stringified. -If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). +If you want to stringify a JSON object, use `JSON.stringifyWithReplacerAndIndent` instead. ## Examples ```rescript -let json = Dict.fromArray([ +let dict = Dict.fromArray([ ("foo", JSON.Encode.string("bar")), ("hello", JSON.Encode.string("world")), ("someNumber", JSON.Encode.int(42)), @@ -307,7 +357,7 @@ let replacer = (key, value) => { } } -JSON.stringifyAnyWithReplacerAndIndent(json, replacer, 2) +JSON.stringifyAnyWithReplacerAndIndent(dict, replacer, 2) // { // "foo": "BAR", // "hello": "WORLD", @@ -326,6 +376,67 @@ BigInt.fromInt(0)->JSON.stringifyAny external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => option = "JSON.stringify" +/** +`stringifyAnyWithFilter(json, filter)` + +Converts any type to a JSON string. +The filter is an array of keys, which should be included in the output. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). +If you want to stringify a JSON object, use `JSON.stringifyWithFilter` instead. + +## Examples +```rescript +let dict = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) + +JSON.stringifyAnyWithFilter(dict, ["foo", "someNumber"]) +// {"foo": "bar","someNumber": 42} + +JSON.stringifyAny(() => "hello world") +// None + +BigInt.fromInt(0)->JSON.stringifyAny +// exception +``` +*/ +@raises @val external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify" + +/** +`stringifyAnyWithFilterAndIndent(json, filter, indentation)` + +Converts any type to a JSON string. The output will be indented. +The filter is an array of keys, which should be included in the output. +Stringifing a function or `undefined` will return `None`. +If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). +If you want to stringify a JSON object, use `JSON.stringifyWithFilterAndIndent` instead. + +## Examples +```rescript +let dict = Dict.fromArray([ + ("foo", JSON.Encode.string("bar")), + ("hello", JSON.Encode.string("world")), + ("someNumber", JSON.Encode.int(42)), +]) + +JSON.stringifyAnyWithFilterAndIndent(dict, ["foo", "someNumber"], 2) +// { +// "foo": "bar", +// "someNumber": 42 +// } + +JSON.stringifyAny(() => "hello world") +// None + +BigInt.fromInt(0)->JSON.stringifyAny +// exception +``` +*/ +@raises @val external stringifyAnyWithFilterAndIndent: ('a, array, int) => string = "JSON.stringify" + module Classify: { /** A type representing a JavaScript type. From 83319d112751a702818eb5bcfa13487fc9a0e193 Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 10:42:22 +0100 Subject: [PATCH 07/19] fix formatting --- src/Core__JSON.resi | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 35c2d43b..67a537d5 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -200,7 +200,8 @@ JSON.stringifyWithFilter(json, ["foo", "someNumber"]) // {"foo":"bar","someNumber":42} ``` */ -@val external stringifyWithFilter: (t, array) => string = "JSON.stringify" +@val +external stringifyWithFilter: (t, array) => string = "JSON.stringify" /** `stringifyWithFilterAndIndent(json, filter, indentation)` @@ -225,7 +226,8 @@ JSON.stringifyWithFilterAndIndent(json, ["foo", "someNumber"], 2) // } ``` */ -@val external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON.stringify" +@val +external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON.stringify" /** `stringifyAny(any)` @@ -403,7 +405,9 @@ BigInt.fromInt(0)->JSON.stringifyAny // exception ``` */ -@raises @val external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify" +@raises +@val +external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify" /** `stringifyAnyWithFilterAndIndent(json, filter, indentation)` @@ -435,7 +439,9 @@ BigInt.fromInt(0)->JSON.stringifyAny // exception ``` */ -@raises @val external stringifyAnyWithFilterAndIndent: ('a, array, int) => string = "JSON.stringify" +@raises +@val +external stringifyAnyWithFilterAndIndent: ('a, array, int) => string = "JSON.stringify" module Classify: { /** From cd7b17835e57b2d1a936c691cbe5bda7327766ef Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 12:53:30 +0100 Subject: [PATCH 08/19] fix wording --- src/Core__JSON.resi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 67a537d5..f77f05be 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -233,7 +233,7 @@ external stringifyWithFilterAndIndent: (t, array, int) => string = "JSON `stringifyAny(any)` Converts any type to a JSON string. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringify` instead. @@ -263,7 +263,7 @@ external stringifyAny: 'a => option = "JSON.stringify" `stringifyAnyWithIndent(any, indentation)` Converts any type to a JSON string. The output will be indented. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithIndent` instead. @@ -298,7 +298,7 @@ external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option Converts any type to a JSON string. The replacer describes how the value should be transformed. It is a function which receives a key and a value. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithReplacer` instead. @@ -338,7 +338,7 @@ external stringifyAnyWithReplacer: ('a, (string, t) => t) => option = "J Converts any type to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithReplacerAndIndent` instead. @@ -383,7 +383,7 @@ external stringifyAnyWithReplacerAndIndent: ('a, (string, t) => t, int) => optio Converts any type to a JSON string. The filter is an array of keys, which should be included in the output. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithFilter` instead. @@ -414,7 +414,7 @@ external stringifyAnyWithFilter: ('a, array) => string = "JSON.stringify Converts any type to a JSON string. The output will be indented. The filter is an array of keys, which should be included in the output. -Stringifing a function or `undefined` will return `None`. +Stringifying a function or `undefined` will return `None`. If the value contains circular references or `BigInt`s, the function will throw a JavaScript exception (TypeError). If you want to stringify a JSON object, use `JSON.stringifyWithFilterAndIndent` instead. From 9590fe2d1aa5ed5e15a270cf63c8ab05592b9a7d Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sat, 4 Mar 2023 13:04:31 +0100 Subject: [PATCH 09/19] remove JSON.Encode.any and changed JSON.parseExnWithReviver accordingly --- src/Core__JSON.res | 1 - src/Core__JSON.resi | 28 ++++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Core__JSON.res b/src/Core__JSON.res index 08776895..16f28e36 100644 --- a/src/Core__JSON.res +++ b/src/Core__JSON.res @@ -57,7 +57,6 @@ module Encode = { external float: float => t = "%identity" external object: Core__Dict.t => t = "%identity" external array: array => t = "%identity" - external any: 'a => t = "%identity" } module Decode = { diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index f77f05be..d8026250 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -40,20 +40,22 @@ It returns a JSON type. ## Examples ```rescript let reviver = (key, value) => { - if key->String.toLowerCase->String.includes("date") { - value->JSON.Decode.string->Option.map(Date.fromString)->JSON.Encode.any - } else { - value + let valueType = JSON.Classify.classify(value) + + switch valueType { + | String(string) => string->String.toUpperCase->JSON.Encode.string + | Number(number) => (number *. 2.0)->JSON.Encode.float + | _ => value } } -let jsonString = `{"parseAsDate":"2023-02-26","parseAsString":"2023-02-26"}` +let jsonString = `{"hello":"world","someNumber":21}` try { - JSON.parseExnWithReviver(jsonString, reviver) - // { parseAsDate: 2023-02-26T00:00:00.000Z, parseAsString: '2023-02-26' } + JSON.parseExnWithReviver(jsonString, reviver)->Console.log + // { hello: 'WORLD', someNumber: 42 } - JSON.parseExnWithReviver("", reviver) + JSON.parseExnWithReviver("", reviver)->Console.log // error } catch { | Js.Exn.Error(_) => Console.log("error") @@ -547,16 +549,6 @@ module Encode: { ``` */ external array: array => t = "%identity" - - /** - Returns any as a JSON object. - - ## Examples - ```rescript - JSON.Encode.any("test") - ``` - */ - external any: 'a => t = "%identity" } module Decode: { From 705a84d1c054337228c748f6ae52c7a31eb2f2ae Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sun, 5 Mar 2023 08:47:35 +0100 Subject: [PATCH 10/19] examples: change Js.Exn to Exn, remove whitespace in comment --- src/Core__JSON.resi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index d8026250..7922afa5 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -1,5 +1,5 @@ /*** - Functions for interacting with JSON. +Functions for interacting with JSON. */ /** @@ -22,7 +22,7 @@ try { JSON.parseExn("") // error } catch { -| Js.Exn.Error(obj) => Console.log("error") +| Exn.Error(obj) => Console.log("error") } ``` */ @@ -58,7 +58,7 @@ try { JSON.parseExnWithReviver("", reviver)->Console.log // error } catch { -| Js.Exn.Error(_) => Console.log("error") +| Exn.Error(_) => Console.log("error") } ``` */ From b363d78078c37a0fc5ae1f90f22d72ef6f072bee Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Sun, 5 Mar 2023 08:50:32 +0100 Subject: [PATCH 11/19] add exceptions block to functions which will throw errors --- src/Core__JSON.resi | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 7922afa5..854bf971 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -25,6 +25,10 @@ try { | Exn.Error(obj) => Console.log("error") } ``` + +## Exceptions + +- Raises a SyntaxError (Exn.t) if the string isn't valid JSON. */ @raises @val @@ -61,6 +65,10 @@ try { | Exn.Error(_) => Console.log("error") } ``` + +## Exceptions + +- Raises a SyntaxError if the string isn't valid JSON. */ @raises @val @@ -256,6 +264,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val @@ -290,6 +303,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val @@ -330,6 +348,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val @@ -374,6 +397,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val @@ -406,6 +434,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val @@ -440,6 +473,11 @@ JSON.stringifyAny(() => "hello world") BigInt.fromInt(0)->JSON.stringifyAny // exception ``` + +## Exceptions + +- Raises a TypeError if the value contains circular references. +- Raises a TypeError if the value contains `BigInt`s. */ @raises @val From 01821adee8a4408063909f42383b7d2e2daa6e9a Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:00:28 +0100 Subject: [PATCH 12/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 854bf971..55b7055d 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -16,7 +16,7 @@ It returns a JSON type. ## Examples ```rescript try { - JSON.parseExn(`{"foo":"bar","hello":"world"}`) + let _ = JSON.parseExn(`{"foo":"bar","hello":"world"}`) // { foo: 'bar', hello: 'world' } JSON.parseExn("") From a9d63194823a8abeb54852dd80fd7cb138ffba08 Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:00:43 +0100 Subject: [PATCH 13/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 55b7055d..b292a528 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -19,7 +19,7 @@ try { let _ = JSON.parseExn(`{"foo":"bar","hello":"world"}`) // { foo: 'bar', hello: 'world' } - JSON.parseExn("") + let _ = JSON.parseExn("") // error } catch { | Exn.Error(obj) => Console.log("error") From b335fe2759b2c9df5c46f81efaaa1fe6240b28e4 Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:01:05 +0100 Subject: [PATCH 14/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index b292a528..7cad0039 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -30,7 +30,7 @@ try { - Raises a SyntaxError (Exn.t) if the string isn't valid JSON. */ -@raises +@raises(Exn.Error) @val external parseExn: string => t = "JSON.parse" From 58b2ed072aebdd32968ee3699bfce3749e6b9c43 Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:01:15 +0100 Subject: [PATCH 15/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 7cad0039..f88fe119 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -270,7 +270,7 @@ BigInt.fromInt(0)->JSON.stringifyAny - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. */ -@raises +@raises(Exn.Error) @val external stringifyAny: 'a => option = "JSON.stringify" From 639f536aac35e9f4abbcef2e31ee4f9267d8033b Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:01:37 +0100 Subject: [PATCH 16/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index f88fe119..2aff7a5b 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -496,7 +496,7 @@ module Classify: { | Array(array) /** - Returns the JavaScript type of any value. + Returns the JSON type of any value. ## Examples ```rescript From f3f6fb6e188e071a51d04b024f4a469316fe49c5 Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:01:46 +0100 Subject: [PATCH 17/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 2aff7a5b..4cb93ab0 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -309,7 +309,7 @@ BigInt.fromInt(0)->JSON.stringifyAny - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. */ -@raises +@raises(Exn.Error) @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" From ceac80a42e5ec7cabb1a2b387e1bad13ab601d03 Mon Sep 17 00:00:00 2001 From: Daniel Kirchhof Date: Thu, 9 Mar 2023 23:01:56 +0100 Subject: [PATCH 18/19] Update src/Core__JSON.resi Co-authored-by: Gabriel Nordeborn --- src/Core__JSON.resi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index 4cb93ab0..b7a9a88c 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -70,7 +70,7 @@ try { - Raises a SyntaxError if the string isn't valid JSON. */ -@raises +@raises(Exn.Error) @val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" From dd7f8b13e27a95e4f682d31756aea344a819c53a Mon Sep 17 00:00:00 2001 From: dkirchhof Date: Thu, 9 Mar 2023 23:20:20 +0100 Subject: [PATCH 19/19] fix: change Exn.Error to Exn.t --- src/Core__JSON.resi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index b7a9a88c..32389d70 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -30,7 +30,7 @@ try { - Raises a SyntaxError (Exn.t) if the string isn't valid JSON. */ -@raises(Exn.Error) +@raises(Exn.t) @val external parseExn: string => t = "JSON.parse" @@ -70,7 +70,7 @@ try { - Raises a SyntaxError if the string isn't valid JSON. */ -@raises(Exn.Error) +@raises(Exn.t) @val external parseExnWithReviver: (string, (string, t) => t) => t = "JSON.parse" @@ -270,7 +270,7 @@ BigInt.fromInt(0)->JSON.stringifyAny - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. */ -@raises(Exn.Error) +@raises(Exn.t) @val external stringifyAny: 'a => option = "JSON.stringify" @@ -309,7 +309,7 @@ BigInt.fromInt(0)->JSON.stringifyAny - Raises a TypeError if the value contains circular references. - Raises a TypeError if the value contains `BigInt`s. */ -@raises(Exn.Error) +@raises(Exn.t) @val external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify"