-
Notifications
You must be signed in to change notification settings - Fork 7
classify: filter undefined values from JS objects #86
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| We can classify the JSON produced by `to_json` for a record with a dropped optional field: | ||
| $ echo ' | ||
| > open Melange_json.Primitives | ||
| > type t = {a: int option; [@json.option] [@json.drop_default]} [@@deriving to_json] | ||
| > let () = | ||
| > match Melange_json.classify (to_json {a = None}) with | ||
| > | `Assoc xs -> xs |> List.iter (fun (k, v) -> | ||
| > let _ = k in | ||
| > let _v = Melange_json.classify v in | ||
| > ()); | ||
| > print_endline "OK" | ||
| > | _ -> print_endline "ERROR: Expected an object" | ||
| > ' | ./run.sh | ||
| === ppx output:native === | ||
| open Melange_json.Primitives | ||
| type t = { | ||
| a: int option [@json.option ][@json.drop_default ]}[@@deriving to_json] | ||
| include | ||
| struct | ||
| let _ = fun (_ : t) -> () | ||
| [@@@ocaml.warning "-39-11-27"] | ||
| let rec to_json = | ||
| (fun x -> | ||
| match x with | ||
| | { a = x_a } -> | ||
| `Assoc | ||
| (let bnds__001_ = [] in | ||
| let bnds__001_ = | ||
| match x_a with | ||
| | Stdlib.Option.None -> bnds__001_ | ||
| | Stdlib.Option.Some _ -> | ||
| ("a", ((option_to_json int_to_json) x_a)) :: bnds__001_ in | ||
| bnds__001_) : t -> Yojson.Basic.t) | ||
| let _ = to_json | ||
| end[@@ocaml.doc "@inline"][@@merlin.hide ] | ||
| let () = | ||
| match Melange_json.classify (to_json { a = None }) with | ||
| | `Assoc xs -> | ||
| (xs |> | ||
| (List.iter | ||
| (fun (k, v) -> | ||
| let _ = k in let _v = Melange_json.classify v in ())); | ||
| print_endline "OK") | ||
| | _ -> print_endline "ERROR: Expected an object" | ||
| === ppx output:browser === | ||
| open Melange_json.Primitives | ||
| type t = { | ||
| a: int option [@json.option ][@json.drop_default ]}[@@deriving to_json] | ||
| include | ||
| struct | ||
| let _ = fun (_ : t) -> () | ||
| [@@@ocaml.warning "-39-11-27"] | ||
| let rec to_json = | ||
| (fun x -> | ||
| match x with | ||
| | { a = x_a } -> | ||
| (Obj.magic | ||
| ([%mel.obj | ||
| { | ||
| a = | ||
| (match x_a with | ||
| | Stdlib.Option.None -> Js.Undefined.empty | ||
| | Stdlib.Option.Some _ -> | ||
| Js.Undefined.return | ||
| ((option_to_json int_to_json) x_a)) | ||
| }]) : Js.Json.t) : t -> Js.Json.t) | ||
| let _ = to_json | ||
| end[@@ocaml.doc "@inline"][@@merlin.hide ] | ||
| let () = | ||
| match Melange_json.classify (to_json { a = None }) with | ||
| | `Assoc xs -> | ||
| (xs |> | ||
| (List.iter | ||
| (fun (k, v) -> | ||
| let _ = k in let _v = Melange_json.classify v in ())); | ||
| print_endline "OK") | ||
| | _ -> print_endline "ERROR: Expected an object" | ||
| === stdout:native === | ||
| OK | ||
| === stdout:js === | ||
| OK |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,18 @@ module J = Js.Json | |
|
|
||
| type t = J.t | ||
|
|
||
| let dict_to_list_without_undefined dict = | ||
| let keys = Js.Dict.keys dict in | ||
| let l = Array.length keys in | ||
| let xs = ref [] in | ||
| for i = l - 1 downto 0 do | ||
| let key = Array.unsafe_get keys i in | ||
| let value = Js.Dict.unsafeGet dict key in | ||
| if not ((Obj.magic value : _ Js.Undefined.t) == Js.undefined) then | ||
| xs := (key, value) :: !xs | ||
| done; | ||
| !xs | ||
|
Comment on lines
+5
to
+15
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably there is some performance issues, but why don't do this: let dict_to_list_without_undefined dict =
Js.Dict.entries dict
|> Array.to_list
|> List.filter (fun (_, value) ->
not ((Obj.magic value : _ Js.Undefined.t) == Js.undefined))
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or let dict_to_list_without_undefined dict =
Array.fold_right
(fun (key, value) acc ->
if not ((Obj.magic value : _ Js.Undefined.t) == Js.undefined) then
(key, value) :: acc
else acc)
(Js.Dict.entries dict) []
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I wanted to reduce number of allocations as much as possible, so no intermediate lists/arrays. |
||
|
|
||
| let classify : | ||
| t -> | ||
| [ `Null | ||
|
|
@@ -27,8 +39,9 @@ let classify : | |
| let xs = Array.to_list (Obj.magic json : t array) in | ||
| `List xs | ||
| else | ||
| let xs = Js.Dict.entries (Obj.magic json : t Js.Dict.t) in | ||
| `Assoc (Array.to_list xs) | ||
| `Assoc | ||
| (dict_to_list_without_undefined | ||
| (Obj.magic json : t Js.Dict.t)) | ||
| | typ -> failwith ("unknown JSON value type: " ^ typ) | ||
|
|
||
| let declassify : | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably the same reason of the other comment, but why not
Js.typeof value <> "undefined"in this case instead ofObj.magic?