I am looking at this article here Better interop with customizable variants | ReScript Blog on the section where it shows an example of writing your own JSON serializer/deserializer code.
On the other hand, I am also aware of https://github.com/rescript-association/rescript-core/blob/main/src/Core__JSON.res
I might be confusing myself, but officially what is the recommended way, starting from ReScript 11, to serialize and de-serialize JSON?
spyder
October 16, 2023, 12:47am
2
It depends how much you control the JSON input. The technique from the article is great if you are certain the input will be in the correct shape, but it lacks error messages should validation fail (it just returns None
).
There are a few community libraries for managing JSON, but I don’t know if any of them are officially recommended so I won’t link to them (yet).
This is not JSON “support”, it’s just a binding to the JavaScript JSON api. It can be used to implement JSON serialisation and deserialisation, and many of the community efforts rely on it.
It depends how much you control the JSON input. The technique from the article is great if you are certain the input will be in the correct shape, but it lacks error messages should validation fail (it just returns None
).
Thanks, I think it can easily be modified to return result instead of option.
This is not JSON “support”, it’s just a binding to the JavaScript JSON api. It can be used to implement JSON serialisation and deserialisation, and many of the community efforts rely on it.
What is the relationship between that one and this one Js.Json | ReScript API
Could you give a small tiny example on how I could use that binding?
Js.Json | ReScript API This doc would be updated soon with new modeling of Json in the compiler v11. https://github.com/rescript-lang/rescript-compiler/blob/master/jscomp/others/js_json.res
https://github.com/rescript-association/rescript-core/blob/main/src/Core__JSON.res This is core lib apis for Js.Json.t that is defined in the compiler above.
Back to your question about how to serialized and deserialize the Json data, I think there are two ways you can choose:
Using std/core lib
This is now idomatical way to handle Json data with v11: Better interop with customizable variants | ReScript Blog
Using 3rd party lib
There are some libraries to handle the Json data. I’m not going to link here, but you can refer to the benchmark: ReScript decoding libraries benchmark
EDIT: the benchmark page seems updated that is missing some libraries compat to ReScript.
Here are some libraries I know:
rescript-struct
ppx_spice
bs-atdgen
3 Likes
DZakh
October 16, 2023, 5:53am
5
Yeah, I mistook the fork and broken the page by syncing it with original master
1 Like
Thank you for clarifying!
1 Like
I wonder if this looks alright. I don’t like the way I am decoding the array below.
type t = {
from: string,
message: string,
timestamp: float,
}
let encode = (message) => {
[
("from", Js.Json.string(message.from)),
("message", Js.Json.string(message.message)),
("timestamp", Js.Json.number(message.timestamp)),
]
-> Dict.fromArray
-> Js.Json.object_
}
let serializeOne = (payload) => {
payload
-> encode
-> Js.Json.stringify
}
let serializeMany = (payload) => {
payload
-> Array.map(encode)
-> Js.Json.array
-> Js.Json.stringify
}
let decode = (obj) => {
switch Js.Json.decodeObject(obj) {
| None => Error("Not an object")
| Some(dict) => {
let from = Dict.get(dict, "from")
let message = Dict.get(dict, "message")
let timestamp = Dict.get(dict, "timestamp")
switch (from, message, timestamp) {
| (Some(from), Some(message), Some(timestamp)) => {
let from = Js.Json.decodeString(from)
let message = Js.Json.decodeString(message)
let timestamp = Js.Json.decodeNumber(timestamp)
switch (from, message, timestamp) {
| (Some(from), Some(message), Some(timestamp)) if from !== "" && message !== "" => {
Ok({ from, message, timestamp })
}
| _ => {
Error("Expected string from and string message")
}
}
}
| _ => Error("Expected non empty from and message")
}
}
}
}
let deserializeOne = (payload) => {
switch Message__Helper.parse(payload) {
| Error(msg) => Error("Error parsing JSON: " ++ msg)
| Ok(json) => decode(json)
}
}
let deserializeMany = (payload) => {
switch Message__Helper.parse(payload) {
| Error(msg) => Error("Error parsing JSON: " ++ msg)
| Ok(json) => {
switch Js.Json.decodeArray(json) {
| None => Error("Not an array")
| Some(array) => {
let result = ref(Ok([]))
let idx = ref(0)
while Result.isOk(result.contents) && idx.contents < Array.length(array) {
let msg = array
-> Array.get(idx.contents)
-> Option.getExn
-> decode
switch msg {
| Error(e) => {
result.contents = Error(e)
}
| Ok(msg) => {
result.contents
-> Result.getExn
-> Array.push(msg)
}
}
idx.contents = idx.contents + 1
}
result.contents
}
}
}
}
}
DZakh
October 23, 2023, 10:07am
8
With rescript-struct
:
type t = {
from: string,
message: string,
timestamp: float,
}
let struct = S.object(s => {
from: s.field("from", S.string),
message: s.field("message", S.string),
timestamp: s.field("timestamp", S.float),
})
let value = data->S.parseWith(struct)
With ppx-spice
:
@spice
type t = {
from: string,
message: string,
timestamp: float,
}
let value = data->t_decode
5 Likes
YKW
May 23, 2025, 3:59am
9
Gonna revitalize this thread, now with v12 on the horizon
How are we decoding and encoding json?
Right now I have projects using spice and sury (formally rescript-struct). I’ve also tried using native rescript, but it’s a nesting nightmare imo
nojaf
May 23, 2025, 6:52am
10
The new dict{}
syntax will be useful. See Dictionary | ReScript Language Manual
1 Like