Skip to content

Instantly share code, notes, and snippets.

@happylinks
Created May 16, 2024 08:40
Show Gist options
  • Save happylinks/d8e9bcdfd94611afc842a17352d28809 to your computer and use it in GitHub Desktop.
Save happylinks/d8e9bcdfd94611afc842a17352d28809 to your computer and use it in GitHub Desktop.
Testing MaybeUndefined in rescript with spice
let omitMaybeUndefined: Js.Json.t => Js.Json.t = %raw(
"function(obj) {Object.keys(obj).forEach(key => obj[key] === 'UNDEFINED' ? delete obj[key] : {}); return obj;}"
)
%%raw(`
let _omitMaybeUndefinedRecursive = (obj) => {
let newObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] === Object(obj[key])) newObj[key] = _omitMaybeUndefinedRecursive(obj[key]);
else if (obj[key] !== 'UNDEFINED') newObj[key] = obj[key];
});
return newObj;
};
`)
let omitMaybeUndefinedRecursive: Js.Json.t => Js.Json.t = %raw(
"function(obj) { return _omitMaybeUndefinedRecursive(obj)}"
)
let insertMaybeUndefined: Js.Json.t => Js.Json.t = %raw(
"function(obj) {Object.keys(obj).forEach(key => obj[key] === undefined ? obj[key] = 'UNDEFINED' : {}); return obj;}"
)
%%raw(`
let _insertMaybeUndefinedRecursive = (obj) => {
let newObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] === Object(obj[key])) newObj[key] = _insertMaybeUndefinedRecursive(obj[key]);
else if (obj[key] === undefined) newObj[key] = 'UNDEFINED';
else newObj[key] = obj[key];
});
return newObj;
};
`)
let insertMaybeUndefinedRecursive: Js.Json.t => Js.Json.t = %raw(
"function(obj) { return _insertMaybeUndefinedRecursive(obj); }"
)
type maybeUndefined<'a> = None | Undefined | Some('a)
let maybeUndefinedToJson = (encoder, opt: maybeUndefined<'a>): Js.Json.t => {
switch opt {
| Some(x) => encoder(x)
| None => Js.Json.null
| Undefined => Js.Json.string("UNDEFINED")
}
}
let maybeUndefinedFromJson = (decoder, json: Js.Json.t) => {
switch Js.Json.classify(json) {
| JSONNull => Ok(None)
| JSONString("UNDEFINED") => Ok(Undefined)
| _ => Belt.Result.map(decoder(json), v => Some(v))
}
}
let maybeUndefined = (maybeUndefinedToJson, maybeUndefinedFromJson)
@spice
type test = {
non_opt: bool,
username: @spice.codec(maybeUndefined) maybeUndefined<string>,
}
Js.log2(
"encode test filled",
{non_opt: true, username: Some("test")}->test3_encode->Object.omitMaybeUndefined,
)
Js.log2(
"encode test some none",
{non_opt: true, username: None}->test3_encode->Object.omitMaybeUndefined,
)
Js.log2(
"encode test none",
{non_opt: true, username: Undefined}->test3_encode->Object.omitMaybeUndefined,
)
Js.log2(
"decode test filled",
%raw(`{"non_opt": true,"username": "test"}`)->Object.insertMaybeUndefined->test3_decode,
)
Js.log2(
"decode test some none",
%raw(`{"non_opt": true,"username": null}`)->Object.insertMaybeUndefined->test3_decode,
)
Js.log2("decode test none", %raw(`{"non_opt": true}`)->test3_decode)
@happylinks
Copy link
Author

happylinks commented May 27, 2024

let nullableToJson = (encoder, opt: option<option<'a>>): Js.Json.t => {
  switch opt {
  | Some(None) => Js.Json.string("__NULL__")
  | Some(x) => encoder(x)
  | None => Js.Json.null
  }
}

let nullableFromJson = (decoder, json: Js.Json.t) => {
  switch Js.Json.classify(json) {
  | JSONNull => Ok(None)
  | JSONString("__NULL__") => Ok(Some(None))
  | _ => Belt.Result.map(decoder(json), v => Some(v))
  }
}

let nullable = (nullableToJson, nullableFromJson)

came up with this now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment