I have a rest API that is expecting json format. I am passing in a record currently which is failing. When I Js.Log the record, I can see that it is a funny array structure, which certainly won’t fly. I assume there is a way I could “convert” that record to a json/js object, but I’m not finding the answer yet.
How do you convert a record to a js object?
I found this in the documentation: https://bucklescript.github.io/docs/en/generate-converters-accessors.html#convert-between-jst-object-and-record
But that seems to only help me with one level of nesting. I have a prop with an array of items, each of which has another nested object. Still not sure how to convert those.
I’ve run into the same pain point (see Logging reason values). I think that your two options are:
-
Create a parallel set of Js.t objects (like the ones your link refers to) that mirror your Reason types at every level and semi-manually write the conversion functions (I say semi-manually because as you know the leaf-nodes can just use jsConverter).
-
Convert your data structures to a
Js.Json.t
. Instead of creating a parallel set of types, one js type for each Reason type, each of your Reason types would have a conversion function toJs.Json.t
. I think being able to derive json, similar to jsConverter, but in a recursive way that goes all the way through your data structures would be extremely valuable. I’m trying to convince the relevant people, but no serious traction yet.
P.S. I haven’t had the time to play around with Js.Json.t too much yet, but here are two relevant links:
Your best bet is to use bs-json to encode your record as json. Though you could do the same with the built in Js_json library.
Heres an example:
module Encode = {
let toJson = credential =>
Json.Encode.(
object_([
("id", credential.id |> int),
("created", credential.created |> int),
("updated", credential.updated |> int),
("client_id", credential.clientId |> int),
("foreign_credential_id", credential.foreignCredentialId |> string),
(
"algorithm",
credential.algorithm |> Hash.algorithmToString |> string
),
("salt", credential.salt |> string),
("derived_key", credential.derivedKey |> string)
])
);
let arrayToJson = arr =>
Belt_Array.map(arr, toJson) |> Json.Encode.jsonArray;
let listToJson = l => Belt_List.toArray(l) |> arrayToJson;
};
I actually faced this same issue last week, and spent a lot of time learning how to fetch JSON, parse and decode it, and then encode something back to JSON.
I’m working on a blog post that explains everything in detail. However, you can preview the working example code here:
See the app.re
file for all the decoding / encoding action.
I have written a post on medium: https://medium.com/@DmytroGladkyi/decode-and-encode-json-in-reasonml-2d484c65cf4e. It has info on how to decode/encode JSON into/from ReasonML structures. In our production code I use this approach to convert ReasonML objects into JSON to be sent into websocket (from JS lib).
in resources limited environment like browser (especially on mobile), any operations is costly so I would suggest you to define a Js.t type with the shape of the object and use %identity converter to convert from Js.Json.t to Js.t