Skip to content

Conversation

@jaredly
Copy link
Contributor

@jaredly jaredly commented Sep 23, 2018

See docs for more info. This also retains debug information if bsc was
with with -bs-g.

This is basically parallel in spirit to OCaml's "input_value" and "output_value", but specialized to the javascript use-case.

[anyToJson value] turns any [value] into a JSON object

This will throw an error if there are any functions anywhere in the value.

[unsafeAnyFromJson json] converts a serialized JSON object back into the bucklescript runtime value.

Warning: marshaling is currently not type-safe. The type of marshaled data is not transmitted along
the value of the data, making it impossible to check that the data read back possesses the type expected
by the context. The return type of this function is given as 'a, but this is misleading: the returned
OCaml value does not possess type 'a for all 'a; it has one, unique type which cannot be determined at
compile-time.

The programmer should explicitly give the expected type of the returned value, using the following syntax:

  (Js.Json.unserializeAnyFromJsonUnsafe json : type)

Anything can happen at run-time if the object does not correspond to the assumed type.

Test Plan:

make libs
make -C jscomp/test all
./node_modules/.bin/mocha jscomp/test/js_json_test.js

See docs for more info. This also retains debug information if bsc was
with with `-bs-g`.

```
[anyToJson value] turns any [value] into a JSON object

This will throw an error if there are any functions anywhere in the value.

[unsafeAnyFromJson json] converts a serialized JSON object back into the bucklescript runtime value.

Warning: marshaling is currently not type-safe. The type of marshaled data is not transmitted along
the value of the data, making it impossible to check that the data read back possesses the type expected
by the context. The return type of this function is given as 'a, but this is misleading: the returned
OCaml value does not possess type 'a for all 'a; it has one, unique type which cannot be determined at
compile-time.

The programmer should explicitly give the expected type of the returned value, using the following syntax:

  (Js.Json.unserializeAnyFromJsonUnsafe json : type)

Anything can happen at run-time if the object does not correspond to the assumed type.
```

Test Plan:
```
make libs
make -C jscomp/tests all
./node_modules/.bin/mocha jscomp/test/js_json_test.js
```
@bobzhang
Copy link
Member

I remember that @cristianoc had something similar.
It is something very useful, my concern is that does it have to be distributed with the compiler or it could be distributed as a third party library? I would prefer it to be distributed as a third party if possible since it would reduce the maintenance overhead

@jaredly
Copy link
Contributor Author

jaredly commented Sep 24, 2018

I think it's important that it be distributed with the compiler because it's dependent on the runtime representation of types (as defined by the compiler). So if the representation changes, then this would need to change. Also this is a thing that everyone asks for, and it would be great to bake it in.

@cristianoc
Copy link
Collaborator

@jaredly here’s the serialization code I have written: https://github.com/cristianoc/REInfer/blob/master/src/Serialize.re

There are a couple of special cases there: such as respecting the distinction between null and undefined.
There are some tests too, that serialize followed by deserialize gives you the same thing back (for things handled in that project). I could run the tests on your serializer.

@bobzhang
Copy link
Member

bobzhang commented Oct 1, 2018

I suggest we may consolidate our work in a third party library(with full coverage test, since it is fragile code). I am okay to have it merged if someone is willing to provide committed maintenance

@chenglou
Copy link
Member

chenglou commented Oct 9, 2018

What can we do to prevent accidentally forgetting the annotation for unserialize?

@jaredly
Copy link
Contributor Author

jaredly commented Oct 10, 2018

I called it Unsafe to try to help that :) if we wanted to get into the linting business (which is something I've been thinking about recently, actually), we could easily lint against unserializeAnyFromJsonUnsafe not being wrapped in a type constraint

@htzh
Copy link
Contributor

htzh commented Oct 31, 2018

@jaredly Is this solution to provide a native/portable version of Js.Json.stringifyAny? For js target stringifyAny seems to work well. For deserialization I just read back the data in js and declare it [@bs.val] external data: someDataType = "";.

@htzh
Copy link
Contributor

htzh commented Oct 31, 2018

@jaredly @bobzhang I now realized this proposal is for JS specialization. Is there a true advantage over Js.Json.stringifyAny? stringifyAny maps to the browser native implementation stringify and is therefore zero maintenance.

@arnarthor
Copy link
Contributor

arnarthor commented Nov 13, 2018

@htzh yes, this would preserve the types on both ends because Bucklescript does some things in the compiled code that isn't part of JSON stringify. For example it augments arrays with a .tag attribute for Variants and some similar container types.

As soon as you try to send a Variant to the server with Js.Json.stringifyAny, it looses it's type information so the server won't be able to reliably pattern match on that Variant after doing Js.Json.parse

By using the proposed functions, you could share types between client and server and not have to write any bindings on either side since these functions would convert these data types to the same JS format that the compiler uses to identify types.

@bobzhang
Copy link
Member

bobzhang commented Apr 3, 2021

note something of similar functionalities are added into Js.Json.
Notably, deserializeUnsafe, serializeExn

@bobzhang bobzhang closed this Apr 3, 2021
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

Successfully merging this pull request may close these issues.

6 participants