@kaiko.io/rescript-deser 4.0.0-beta.2 → 4.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/bs/.bsdeps CHANGED
@@ -1,8 +1,8 @@
1
- 11.0.0-beta.4
1
+ 11.0.0-rc.4
2
2
  /home/manu/src/kaiko/rescript-deser
3
3
  0
4
4
  bsconfig.json 0x1.92beacc6fcbbbp+30
5
- tests 0x1.92be24d20cc42p+30
6
- src/ 0x1.92be2684bc9cdp+30
5
+ tests 0x1.93fb8b23e3f01p+30
6
+ src/ 0x1.93fb8b23e3f01p+30
7
7
  ===
8
- /home/manu/src/kaiko/rescript-deser/node_modules/rescript/linux/rescript.exe 0x1.92e953b26353bp+30
8
+ /home/manu/src/kaiko/rescript-deser/node_modules/rescript/linux/rescript.exe 0x1.94b388560105ep+30
@@ -1,2 +1,2 @@
1
- #Start(1690474971872)
2
- #Done(1690474971872)
1
+ #Start(1697442090837)
2
+ #Done(1697442090837)
package/lib/bs/.ninja_log CHANGED
@@ -1,31 +1,19 @@
1
1
  # ninja log v6
2
- 0 6 1690472976980944692 tests/QUnit.ast f5cbe90bf025978b
3
- 0 7 1690472976980944692 tests/index.ast af1b9dde75b669ce
4
- 0 8 1690472976980944692 src/JSON.ast ec417eedaf9813d7
5
- 6 9 1690472976984278051 tests/QUnit.d 4a2631c992d93ce7
6
- 7 9 1690472976984278051 tests/index.d 5a4db9cdecd186b3
7
- 8 10 1690472976984278051 src/JSON.d cd2d6773c781340f
8
- 9 17 1690472976990944772 tests/QUnit.cmj 228de0204beccf77
9
- 9 17 1690472976990944772 tests/QUnit.cmi 228de0204beccf77
10
- 9 17 1690472976990944772 ../es6/tests/QUnit.js 228de0204beccf77
11
- 9 17 1690472976990944772 ../js/tests/QUnit.js 228de0204beccf77
12
- 10 30 1690472977004278213 src/JSON.cmj cd7188cec2df38d4
13
- 10 30 1690472977004278213 src/JSON.cmi cd7188cec2df38d4
14
- 10 30 1690472977004278213 ../es6/src/JSON.js cd7188cec2df38d4
15
- 10 30 1690472977004278213 ../js/src/JSON.js cd7188cec2df38d4
16
- 30 42 1690472977014278294 tests/index.cmj bfa81ebb23ddb1d3
17
- 30 42 1690472977014278294 tests/index.cmi bfa81ebb23ddb1d3
18
- 30 42 1690472977014278294 ../es6/tests/index.js bfa81ebb23ddb1d3
19
- 30 42 1690472977014278294 ../js/tests/index.js bfa81ebb23ddb1d3
20
- 0 8 1690472976984278051 tests/QUnit.cmj 2ec5fa040bfd2d9d
21
- 0 8 1690472976984278051 tests/QUnit.cmi 2ec5fa040bfd2d9d
22
- 0 8 1690472976984278051 ../es6/tests/QUnit.js 2ec5fa040bfd2d9d
23
- 0 8 1690472976984278051 ../js/tests/QUnit.js 2ec5fa040bfd2d9d
24
- 0 21 1690472976984278051 src/JSON.cmj 72e6767661d939a8
25
- 0 21 1690472976984278051 src/JSON.cmi 72e6767661d939a8
26
- 0 21 1690472976984278051 ../es6/src/JSON.js 72e6767661d939a8
27
- 0 21 1690472976984278051 ../js/src/JSON.js 72e6767661d939a8
28
- 21 34 1690472977004278213 tests/index.cmj 99dcd7620c5e344f
29
- 21 34 1690472977004278213 tests/index.cmi 99dcd7620c5e344f
30
- 21 34 1690472977004278213 ../es6/tests/index.js 99dcd7620c5e344f
31
- 21 34 1690472977004278213 ../js/tests/index.js 99dcd7620c5e344f
2
+ 0 6 1697442041120968689 tests/QUnit.ast 67b6a0da460567c3
3
+ 0 7 1697442041120968689 tests/index.ast 5536aeeda222362c
4
+ 0 8 1697442041120968689 src/JSON.ast b65d00b367d55de4
5
+ 6 9 1697442041124302115 tests/QUnit.d 4a2631c992d93ce7
6
+ 7 9 1697442041124302115 tests/index.d 5a4db9cdecd186b3
7
+ 8 10 1697442041124302115 src/JSON.d cd2d6773c781340f
8
+ 9 16 1697442041130968965 tests/QUnit.cmj 11defb6b2e52acbf
9
+ 9 16 1697442041130968965 tests/QUnit.cmi 11defb6b2e52acbf
10
+ 9 16 1697442041130968965 ../es6/tests/QUnit.js 11defb6b2e52acbf
11
+ 9 16 1697442041130968965 ../js/tests/QUnit.js 11defb6b2e52acbf
12
+ 10 29 1697442041144302666 src/JSON.cmj f85e720d809b7705
13
+ 10 29 1697442041144302666 src/JSON.cmi f85e720d809b7705
14
+ 10 29 1697442041144302666 ../es6/src/JSON.js f85e720d809b7705
15
+ 10 29 1697442041144302666 ../js/src/JSON.js f85e720d809b7705
16
+ 29 41 1697442041154302941 tests/index.cmj 11fbdd4f70b0d5d2
17
+ 29 41 1697442041154302941 tests/index.cmi 11fbdd4f70b0d5d2
18
+ 29 41 1697442041154302941 ../es6/tests/index.js 11fbdd4f70b0d5d2
19
+ 29 41 1697442041154302941 ../js/tests/index.js 11fbdd4f70b0d5d2
@@ -1,7 +1,7 @@
1
1
  rescript = 1
2
2
  g_finger := /home/manu/src/kaiko/rescript-deser/node_modules/@kaiko.io/rescript-prelude/lib/ocaml/install.stamp
3
3
  rule astj
4
- command = /home/manu/src/kaiko/rescript-deser/node_modules/rescript/linux/bsc.exe -warn-error +8+11+26+27+33+56 -bs-v 11.0.0-beta.4 -uncurried -absname -bs-ast -o $out $i
4
+ command = /home/manu/src/kaiko/rescript-deser/node_modules/rescript/linux/bsc.exe -warn-error +8+11+26+27+33+56 -bs-v 11.0.0-rc.4 -uncurried -absname -bs-ast -o $out $i
5
5
  o tests/index.ast : astj ../../tests/index.res
6
6
  rule deps_dev
7
7
  command = /home/manu/src/kaiko/rescript-deser/node_modules/rescript/linux/bsb_helper.exe -g -hash 84aecc33f8594375b23a1a137b057f93 $in
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -110,9 +110,9 @@ function toString(type_) {
110
110
  case "Array" :
111
111
  return "Array of " + toString(type_._0);
112
112
  case "Tuple" :
113
- return "Tuple of (" + Curry._2(Prelude.$$Array.map, type_._0, toString).join(", ") + ")";
113
+ return "Tuple of (" + Prelude.$$Array.map(type_._0, toString).join(", ") + ")";
114
114
  case "Object" :
115
- var desc = Curry._2(Prelude.$$Array.map, type_._0, (function (param) {
115
+ var desc = Prelude.$$Array.map(type_._0, (function (param) {
116
116
  return param[0] + ": " + toString(param[1]);
117
117
  })).join(", ");
118
118
  return "Object of {" + desc + "}";
@@ -152,9 +152,9 @@ function _taggedToString(tagged) {
152
152
  case "JSONNumber" :
153
153
  return "Number(" + String(tagged._0) + ")";
154
154
  case "JSONObject" :
155
- return "Object(" + Prelude.$$default(JSON.stringify(tagged._0), "...") + ")";
155
+ return "Object(" + Prelude.default(JSON.stringify(tagged._0), "...") + ")";
156
156
  case "JSONArray" :
157
- return "Array(" + Prelude.$$default(JSON.stringify(tagged._0), "...") + ")";
157
+ return "Array(" + Prelude.default(JSON.stringify(tagged._0), "...") + ")";
158
158
 
159
159
  }
160
160
  }
@@ -306,7 +306,7 @@ function fromUntagged(untagged, _shape, self) {
306
306
  } else {
307
307
  if (match.TAG === "JSONArray") {
308
308
  var shape$1 = shape._0;
309
- return Curry._2(Prelude.$$Array.map, match._0, (function(shape$1){
309
+ return Prelude.$$Array.map(match._0, (function(shape$1){
310
310
  return function (item) {
311
311
  return fromUntagged(item, shape$1, self);
312
312
  }
@@ -344,7 +344,7 @@ function fromUntagged(untagged, _shape, self) {
344
344
  } else {
345
345
  if (match.TAG === "JSONObject") {
346
346
  var values = match._0;
347
- return Curry._1(Prelude.Dict.fromArray, Curry._2(Prelude.$$Array.map, shape._0, (function(values){
347
+ return Curry._1(Prelude.Dict.fromArray, Prelude.$$Array.map(shape._0, (function(values){
348
348
  return function (param) {
349
349
  var field = param[0];
350
350
  var value;
@@ -426,7 +426,7 @@ function fromUntagged(untagged, _shape, self) {
426
426
  exit = 1;
427
427
  } else {
428
428
  if (match.TAG === "JSONArray") {
429
- return Curry._2(Prelude.$$Array.map, Prelude.$$Array.keepSome(Curry._2(Prelude.$$Array.map, Curry._2(Prelude.$$Array.map, match._0, shape._0.fromJSON), Prelude.Result.warn)), (function (prim) {
429
+ return Prelude.$$Array.map(Prelude.$$Array.keepSome(Prelude.$$Array.map(Prelude.$$Array.map(match._0, shape._0.fromJSON), Prelude.Result.warn)), (function (prim) {
430
430
  return prim;
431
431
  }));
432
432
  }
@@ -518,8 +518,8 @@ function checkFieldsSanity(name, _fields, _optional) {
518
518
  } else {
519
519
  switch (fields.TAG) {
520
520
  case "Tuple" :
521
- return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Curry._2(Prelude.$$Array.mapWithIndex, fields._0, (function(optional){
522
- return function (index, field) {
521
+ return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Prelude.$$Array.mapWithIndex(fields._0, (function(optional){
522
+ return function (field, index) {
523
523
  return function () {
524
524
  return checkFieldsSanity(name + "[" + String(index) + "]", field, optional);
525
525
  };
@@ -528,7 +528,7 @@ function checkFieldsSanity(name, _fields, _optional) {
528
528
 
529
529
  }));
530
530
  case "Object" :
531
- return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Curry._2(Prelude.$$Array.map, fields._0, (function(optional){
531
+ return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Prelude.$$Array.map(fields._0, (function(optional){
532
532
  return function (param) {
533
533
  var field = param[1];
534
534
  var fieldName = param[0];
@@ -606,7 +606,7 @@ var Field = {
606
606
 
607
607
  function MakeDeserializer(S) {
608
608
  var fields = S.fields;
609
- var name = "Deserializer " + "JSON" + ", " + "File \"JSON.res\", line 320, characters 39-47";
609
+ var name = "Deserializer " + "JSON" + ", " + "File \"JSON.res\", line 329, characters 39-47";
610
610
  var checkFieldsSanity$1 = function () {
611
611
  return checkFieldsSanity(name, fields, false);
612
612
  };
@@ -630,9 +630,35 @@ function MakeDeserializer(S) {
630
630
  _0: res
631
631
  };
632
632
  };
633
+ var fromAny = function (any) {
634
+ var match = typeof any;
635
+ if (match === "string") {
636
+ var parsed;
637
+ try {
638
+ parsed = JSON.parse(any);
639
+ }
640
+ catch (exn){
641
+ return {
642
+ TAG: "Error",
643
+ _0: "Could parse string as JSON"
644
+ };
645
+ }
646
+ return fromJSON(parsed);
647
+ }
648
+ try {
649
+ return fromJSON(any);
650
+ }
651
+ catch (exn$1){
652
+ return {
653
+ TAG: "Error",
654
+ _0: "Could not deserialize the data"
655
+ };
656
+ }
657
+ };
633
658
  return {
634
659
  name: name,
635
660
  fromJSON: fromJSON,
661
+ fromAny: fromAny,
636
662
  checkFieldsSanity: checkFieldsSanity$1
637
663
  };
638
664
  }
@@ -234,7 +234,11 @@ Qunit.module("Recursive deserializer", (function (param) {
234
234
  "records",
235
235
  {
236
236
  TAG: "Deserializer",
237
- _0: List
237
+ _0: {
238
+ name: List.name,
239
+ fromJSON: List.fromJSON,
240
+ checkFieldsSanity: List.checkFieldsSanity
241
+ }
238
242
  }
239
243
  ],
240
244
  [
@@ -111,9 +111,9 @@ function toString(type_) {
111
111
  case "Array" :
112
112
  return "Array of " + toString(type_._0);
113
113
  case "Tuple" :
114
- return "Tuple of (" + Curry._2(Prelude.$$Array.map, type_._0, toString).join(", ") + ")";
114
+ return "Tuple of (" + Prelude.$$Array.map(type_._0, toString).join(", ") + ")";
115
115
  case "Object" :
116
- var desc = Curry._2(Prelude.$$Array.map, type_._0, (function (param) {
116
+ var desc = Prelude.$$Array.map(type_._0, (function (param) {
117
117
  return param[0] + ": " + toString(param[1]);
118
118
  })).join(", ");
119
119
  return "Object of {" + desc + "}";
@@ -153,9 +153,9 @@ function _taggedToString(tagged) {
153
153
  case "JSONNumber" :
154
154
  return "Number(" + String(tagged._0) + ")";
155
155
  case "JSONObject" :
156
- return "Object(" + Prelude.$$default(JSON.stringify(tagged._0), "...") + ")";
156
+ return "Object(" + Prelude.default(JSON.stringify(tagged._0), "...") + ")";
157
157
  case "JSONArray" :
158
- return "Array(" + Prelude.$$default(JSON.stringify(tagged._0), "...") + ")";
158
+ return "Array(" + Prelude.default(JSON.stringify(tagged._0), "...") + ")";
159
159
 
160
160
  }
161
161
  }
@@ -307,7 +307,7 @@ function fromUntagged(untagged, _shape, self) {
307
307
  } else {
308
308
  if (match.TAG === "JSONArray") {
309
309
  var shape$1 = shape._0;
310
- return Curry._2(Prelude.$$Array.map, match._0, (function(shape$1){
310
+ return Prelude.$$Array.map(match._0, (function(shape$1){
311
311
  return function (item) {
312
312
  return fromUntagged(item, shape$1, self);
313
313
  }
@@ -345,7 +345,7 @@ function fromUntagged(untagged, _shape, self) {
345
345
  } else {
346
346
  if (match.TAG === "JSONObject") {
347
347
  var values = match._0;
348
- return Curry._1(Prelude.Dict.fromArray, Curry._2(Prelude.$$Array.map, shape._0, (function(values){
348
+ return Curry._1(Prelude.Dict.fromArray, Prelude.$$Array.map(shape._0, (function(values){
349
349
  return function (param) {
350
350
  var field = param[0];
351
351
  var value;
@@ -427,7 +427,7 @@ function fromUntagged(untagged, _shape, self) {
427
427
  exit = 1;
428
428
  } else {
429
429
  if (match.TAG === "JSONArray") {
430
- return Curry._2(Prelude.$$Array.map, Prelude.$$Array.keepSome(Curry._2(Prelude.$$Array.map, Curry._2(Prelude.$$Array.map, match._0, shape._0.fromJSON), Prelude.Result.warn)), (function (prim) {
430
+ return Prelude.$$Array.map(Prelude.$$Array.keepSome(Prelude.$$Array.map(Prelude.$$Array.map(match._0, shape._0.fromJSON), Prelude.Result.warn)), (function (prim) {
431
431
  return prim;
432
432
  }));
433
433
  }
@@ -519,8 +519,8 @@ function checkFieldsSanity(name, _fields, _optional) {
519
519
  } else {
520
520
  switch (fields.TAG) {
521
521
  case "Tuple" :
522
- return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Curry._2(Prelude.$$Array.mapWithIndex, fields._0, (function(optional){
523
- return function (index, field) {
522
+ return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Prelude.$$Array.mapWithIndex(fields._0, (function(optional){
523
+ return function (field, index) {
524
524
  return function () {
525
525
  return checkFieldsSanity(name + "[" + String(index) + "]", field, optional);
526
526
  };
@@ -529,7 +529,7 @@ function checkFieldsSanity(name, _fields, _optional) {
529
529
 
530
530
  }));
531
531
  case "Object" :
532
- return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Curry._2(Prelude.$$Array.map, fields._0, (function(optional){
532
+ return Curry._2(Prelude.ManyResults.map, Prelude.ManyResults.bailU(Prelude.$$Array.map(fields._0, (function(optional){
533
533
  return function (param) {
534
534
  var field = param[1];
535
535
  var fieldName = param[0];
@@ -607,7 +607,7 @@ var Field = {
607
607
 
608
608
  function MakeDeserializer(S) {
609
609
  var fields = S.fields;
610
- var name = "Deserializer " + "JSON" + ", " + "File \"JSON.res\", line 320, characters 39-47";
610
+ var name = "Deserializer " + "JSON" + ", " + "File \"JSON.res\", line 329, characters 39-47";
611
611
  var checkFieldsSanity$1 = function () {
612
612
  return checkFieldsSanity(name, fields, false);
613
613
  };
@@ -631,9 +631,35 @@ function MakeDeserializer(S) {
631
631
  _0: res
632
632
  };
633
633
  };
634
+ var fromAny = function (any) {
635
+ var match = typeof any;
636
+ if (match === "string") {
637
+ var parsed;
638
+ try {
639
+ parsed = JSON.parse(any);
640
+ }
641
+ catch (exn){
642
+ return {
643
+ TAG: "Error",
644
+ _0: "Could parse string as JSON"
645
+ };
646
+ }
647
+ return fromJSON(parsed);
648
+ }
649
+ try {
650
+ return fromJSON(any);
651
+ }
652
+ catch (exn$1){
653
+ return {
654
+ TAG: "Error",
655
+ _0: "Could not deserialize the data"
656
+ };
657
+ }
658
+ };
634
659
  return {
635
660
  name: name,
636
661
  fromJSON: fromJSON,
662
+ fromAny: fromAny,
637
663
  checkFieldsSanity: checkFieldsSanity$1
638
664
  };
639
665
  }
@@ -235,7 +235,11 @@ Qunit.module("Recursive deserializer", (function (param) {
235
235
  "records",
236
236
  {
237
237
  TAG: "Deserializer",
238
- _0: List
238
+ _0: {
239
+ name: List.name,
240
+ fromJSON: List.fromJSON,
241
+ checkFieldsSanity: List.checkFieldsSanity
242
+ }
239
243
  }
240
244
  ],
241
245
  [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaiko.io/rescript-deser",
3
- "version": "4.0.0-beta.2",
3
+ "version": "4.0.0-beta.4",
4
4
  "keywords": [
5
5
  "json",
6
6
  "deserializer",
@@ -20,8 +20,8 @@
20
20
  "README.md"
21
21
  ],
22
22
  "dependencies": {
23
- "@kaiko.io/rescript-prelude": "7.0.0-beta.1",
24
- "rescript": "11.0.0-beta.4"
23
+ "@kaiko.io/rescript-prelude": "7.0.0-beta.2",
24
+ "rescript": "11.0.0-rc.4"
25
25
  },
26
26
  "devDependencies": {
27
27
  "esbuild": "^0.15.7",
package/src/JSON.res CHANGED
@@ -23,11 +23,20 @@ module FieldValue = {
23
23
 
24
24
  exception TypeError(string)
25
25
 
26
- @doc("The module type of a built deserializer which is suitable to add as a subparser.")
26
+ @doc("The module type of a deserializer which is suitable to add as a subparser.")
27
+ module type ArgDeserializer = {
28
+ type t
29
+ let name: string
30
+ let fromJSON: Js.Json.t => result<t, string>
31
+ let checkFieldsSanity: unit => result<unit, string>
32
+ }
33
+
34
+ @doc("The module type of a built deserializer.")
27
35
  module type Deserializer = {
28
36
  type t
29
37
  let name: string
30
38
  let fromJSON: Js.Json.t => result<t, string>
39
+ let fromAny: 'a => result<t, string>
31
40
  let checkFieldsSanity: unit => result<unit, string>
32
41
  }
33
42
 
@@ -57,13 +66,13 @@ module Field = {
57
66
  /// expected entries.
58
67
  | Mapping(t)
59
68
 
60
- | Deserializer(module(Deserializer))
69
+ | Deserializer(module(ArgDeserializer))
61
70
 
62
71
  /// A specialized Array of deserialized items that ignores unparsable
63
72
  /// items and returns the valid collection. This saves the user from
64
73
  /// writing 'Array(DefaultWhenInvalid(Optional(Deserializer(module(M)))))'
65
74
  /// and then post-process the list of items with 'Array.keepSome'
66
- | Collection(module(Deserializer))
75
+ | Collection(module(ArgDeserializer))
67
76
  | DefaultWhenInvalid(t, FieldValue.t)
68
77
 
69
78
  // FIXME: this is used to add additional restrictions like variadictInt or
@@ -112,7 +121,7 @@ module Field = {
112
121
  | Date => "Date"
113
122
  | Self => "Self (recursive)"
114
123
  | Collection(m) => {
115
- module M = unpack(m: Deserializer)
124
+ module M = unpack(m: ArgDeserializer)
116
125
  "Collection of " ++ M.name
117
126
  }
118
127
 
@@ -129,7 +138,7 @@ module Field = {
129
138
  | Mapping(t) => `Mapping of ${t->toString}`
130
139
  | Morphism(t, _) => t->toString ++ " to apply a morphism"
131
140
  | Deserializer(m) => {
132
- module M = unpack(m: Deserializer)
141
+ module M = unpack(m: ArgDeserializer)
133
142
  M.name
134
143
  }
135
144
 
@@ -234,7 +243,7 @@ module Field = {
234
243
  | (Morphism(shape, f), _) => untagged->fromUntagged(shape, self)->f->FieldValue.any
235
244
 
236
245
  | (Collection(m), Js.Json.JSONArray(items)) => {
237
- module M = unpack(m: Deserializer)
246
+ module M = unpack(m: ArgDeserializer)
238
247
  items
239
248
  ->Array.map(M.fromJSON)
240
249
  ->Array.map(Result.warn)
@@ -244,7 +253,7 @@ module Field = {
244
253
  }
245
254
 
246
255
  | (Deserializer(m), _) => {
247
- module M = unpack(m: Deserializer)
256
+ module M = unpack(m: ArgDeserializer)
248
257
  switch untagged->M.fromJSON {
249
258
  | Ok(res) => res->FieldValue.any
250
259
  | Error(msg) => raise(TypeError(msg))
@@ -277,7 +286,7 @@ module Field = {
277
286
 
278
287
  | (Collection(mod), _)
279
288
  | (Deserializer(mod), _) => {
280
- module M = unpack(mod: Deserializer)
289
+ module M = unpack(mod: ArgDeserializer)
281
290
  switch M.checkFieldsSanity() {
282
291
  | Ok() => Ok()
283
292
  | Error(msg) => Error(`${name}/ ${msg}`)
@@ -302,7 +311,7 @@ module Field = {
302
311
 
303
312
  | (Tuple(fields), optional) =>
304
313
  fields
305
- ->Array.mapWithIndex((index, field) => () =>
314
+ ->Array.mapWithIndex((field, index) => () =>
306
315
  checkFieldsSanity(`${name}[${index->Int.toString}]`, field, optional))
307
316
  ->ManyResults.bailU
308
317
  ->ManyResults.map(_ => ())
@@ -320,7 +329,10 @@ module MakeDeserializer = (S: Serializable): (Deserializer with type t = S.t) =>
320
329
  %%private(let (loc, _f) = __LOC_OF__(module(S: Serializable)))
321
330
  let name = `Deserializer ${__MODULE__}, ${loc}`
322
331
 
323
- %%private(external _toNativeType: FieldValue.t => t = "%identity")
332
+ %%private(
333
+ external _toNativeType: FieldValue.t => t = "%identity"
334
+ external cast: 'a => 'b = "%identity"
335
+ )
324
336
 
325
337
  @doc("Checks for trivial infinite-recursion in the fields of the module.
326
338
 
@@ -340,4 +352,20 @@ module MakeDeserializer = (S: Serializable): (Deserializer with type t = S.t) =>
340
352
  | exception TypeError(e) => Error(e)
341
353
  }
342
354
  }
355
+
356
+ @doc("Try to parse anything")
357
+ let fromAny = any => {
358
+ switch Js.typeof(any) {
359
+ | "string" =>
360
+ switch any->cast->Js.Json.parseExn {
361
+ | parsed => fromJSON(parsed)
362
+ | exception _ => Error("Could parse string as JSON")
363
+ }
364
+ | _ =>
365
+ switch any->cast->fromJSON {
366
+ | result => result
367
+ | exception _ => Error("Could not deserialize the data")
368
+ }
369
+ }
370
+ }
343
371
  }