Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] How to serialize sum type to json? #1993

Closed
hh9527 opened this issue Jul 10, 2024 · 4 comments
Closed

[Question] How to serialize sum type to json? #1993

hh9527 opened this issue Jul 10, 2024 · 4 comments

Comments

@hh9527
Copy link

hh9527 commented Jul 10, 2024

let Ty = [| 'Num Number, 'Str String |] in 'Num 1 | Ty
$ nickel export t.ncl
error: non serializable term
@yannham
Copy link
Member

yannham commented Jul 15, 2024

Indeed, enums (at least with arguments) can't currently be serialized. Quoting the manual:

Warning 2: enum variants are the only primitive data structure of Nickel that can't be serialized. Indeed, there is no obvious canonical way to encode enum variants in the JSON data model (though many such encodings exist). If you need to serialize and deserialize enum variants, you'll have to explicitly map them to and from serializable data structures (such as records). In general, enum variants are rather expected to be used internally to make nice and ergonomic library APIs.

In particular, if you just want to store a value that is either a string or a number, and serialize it without any tag (that is serialize 'Num 1 as 1 and 'Str "a" as "a"), you could probably directly store either a Number or a String in a field directly. You can write a contract NumberOrString for that. In the coming new version of Nickel, you'll even have an operator (the name is not fixed yet) to do that:

> let Ty = std.contract.any_of [Number, String] in 1 | Ty
> 1 | Ty
1

> "a" | Ty
"a"

If for any reason you really need to keep the enum, you have to transform it to the underlying value at some point. Something like #1170 (comment) could also help, but it's an idea and isn't yet implemented, unfortunately.

@hh9527
Copy link
Author

hh9527 commented Jul 23, 2024

@yannham Thank you for your explaination.

You explaination is very clear, I think I had use nickel in the wrong way.

nickel assume the users to use it in the data-centric-way, but I use it in the type-centric-way.

@yannham
Copy link
Member

yannham commented Jul 25, 2024

You're welcome! I'm going to close for now as the original question was mostly asking about information. Feel free to open other issues if there are other questions or proposals around enums and enums serialization in particularly.

@yannham yannham closed this as completed Jul 25, 2024
@rben01
Copy link
Contributor

rben01 commented Dec 1, 2024

I also faced this issue, and this GitHub issue was the only solution I found. I think that in the docs, in the enum section, there should be a note about the pitfalls of enums (no serializability) and an explanation of how to reimplement them using std.contract.any_of — especially since it seems like std.contract.any_of is the proper user-facing tool (i.e. you should vend std.contract.any_of types/contracts, not enums, for users of your schemas).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants