Closed cevr closed 1 year ago
Hi @cevr. I'm not sure I understand the issue. Can you include any error messages your seeing and/or expected function output compared to actual function output?
Hey @ryb73. Basically, the above will be decoded as such
let project = {
description: undefined, // if null
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: undefined, // if null
isArchived: bool,
};
This causes problems with next.js when it serializes the project
object and sends it to the frontend.
The error is basically do not explicitly set
undefinedvalues, rather set them as
nullor omit them from the object
The desired output is
let project = {
description: null, // if null
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: null, // if null
isArchived: bool,
};
I tried
[@decco.decode]
type project = {
description: Js.nullable(string),
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: Js.nullable(primaryLanguage),
isArchived: bool,
};
But that isn't supported a supported, and I'm very lost on how to write a decoder for that.
Sorry, I'm still confused about your use case. Are you talking about encoding or decoding? Decoding is going from JSON to Reason, encoding is going from Reason to JSON. If you are decoding an option
field, null
will be decoded as None
. If you encode an option
field with a value of None
, it will be encoded as null
.
Could you post the specific code that you're running, the output you expect, and the actual output you're getting?
Ahh, I see.
I'm using this https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering to populate the props of a react component.
[@decco]
type primaryLanguage = {name: string};
[@decco]
type project = {
description: option(string),
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: option(primaryLanguage),
isArchived: bool,
};
[@decco]
type edge = {node: project};
[@decco]
type repositories = {edges: array(edge)};
[@decco]
type user = {repositories};
[@decco]
type response = {user};
let getServerSideProps = _context => {
ProjectsApi.get()
|> Js.Promise.then_((result: array(ProjectsApi.project)) => {
Js.Promise.resolve(
result->Belt.Array.keep(project =>
project.stargazerCount > 1 && !project.isArchived
),
)
})
|> Js.Promise.then_(result => {
let props: props = {projects: result};
Js.Promise.resolve({"props": props});
});
};
The issue arises because the encoding and decoding are being handled internally by the framework I use (nextjs) when it injects props into a component.
So even if I manually encode it within getServerSideProps
, it will not be option(string)
but rather Js.nullable(string)
because I cannot control the decoding when it gets to the component
So the answer again would be to support:
[@decco]
type project = {
description: Js.nullable(string),
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: Js.nullable(primaryLanguage),
isArchived: bool,
};
Does that make sense?
Ok, I think I see. What you could do is use the magic
codec:
[@decco]
type project = {
description: [@decco.codec Decco.Codecs.magic] Js.nullable(string),
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: [@decco.codec Decco.Codecs.magic] Js.nullable(primaryLanguage),
isArchived: bool,
};
This passes through the value as-is without any checking.
ah perfect! Thank you :)
EDIT: Seems to error when used
We've found a bug for you!
/Users/admin/Projects/personal/me/src/api/ProjectsApi.re
This has type: Belt.Result.t('a, 'b) (defined as Belt_Result.t('a, 'b))
Somewhere wanted: Js.Json.t => 'c
FAILED: cannot make progress due to previous errors.
Sorry @cevr, I thought I'd responded to this. Thanks for catching that error, this is something I need to look into.
It's been a while so you've probably worked around this by now, but I think this is one way to work around the bug for now:
[@decco]
type primaryLanguage = {name: string};
type nullableString = Js.nullable(string);
type nullableLanguage = Js.nullable(primaryLanguage);
[@decco]
type project = {
description: [@decco.codec Decco.Codecs.magic] nullableString,
name: string,
stargazerCount: int,
url: string,
id: string,
primaryLanguage: [@decco.codec Decco.Codecs.magic] nullableLanguage,
isArchived: bool,
};
description
andprimaryLanguage
will be decoded asundefined
because they are either string | null. How do I write a decoder so that null values remain null?