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

Add few functions to the utils module #127

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

- Add an opam package `yojson-bench` to deal with benchmarks dependency
(@tmcgilchrist, #117)
- Added utilitaries function `assoc_map`, `assoc_map_filter`, `add`, `update`
and `remove` to the `Utils` module (@panglesd, #127)

### Change

Expand Down
46 changes: 46 additions & 0 deletions lib/util.ml
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,49 @@ let combine (first : t) (second : t) =
match (first, second) with
| (`Assoc a, `Assoc b) -> (`Assoc (a @ b) : t)
| (a, b) -> raise (Invalid_argument "Expected two objects, check inputs")

let assoc_map f json = match json with
| `Assoc l ->
let rec map res l = match l with
[] -> res
| (k,v) :: q -> map ( (k,f (k,v)) :: res) q in
`Assoc (List.rev @@ map [] l)
| js -> typerr "Can't assoc_map over non-object type " js

let assoc_map_filter f json = match json with
| `Assoc l ->
let rec map res l = match l with
[] -> res
| (k,v) :: q ->
match f (k,v) with
None -> map (res) q
| Some v -> map ( (k,v) :: res) q in
`Assoc (List.rev @@ map [] l)
| js -> typerr "Can't assoc_map_filter over non-object type " js

let add json pair = match json with
| `Assoc l -> `Assoc (pair :: l)
| js -> typerr "Can't assoc_map_filter over non-object type " js

let update json (key, value) = match json with
| `Assoc l ->
let rec map res l = match l with
[] -> List.rev res
| (k,v) :: q when k = key ->
List.rev_append res ((k, value) :: q)
| a :: q ->
map (a::res) q in
`Assoc (map [] l)
| js -> typerr "Can't update field of non-object type " js

let remove json key = match json with
| `Assoc l ->
let rec map res l = match l with
[] -> List.rev res
| (k,v) :: q when k = key ->
List.rev_append res q
| a :: q ->
map (a::res) q in
`Assoc (map [] l)
| js -> typerr "Can't remove field on non-object type " js

20 changes: 20 additions & 0 deletions lib/util.mli
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ val keys : t -> string list
val values : t -> t list
(** Return all the value in the given JSON object *)

val add : t -> (string * t) -> t
(** Add an entry to a JSON object *)

val update : t -> (string * t) -> t
(** [update json (key, value)] updates the first field with key [key] of the
JSON object [json] to [value] *)

val remove : t -> string -> t
(** [remove json key] remove the first field with key [key] of the
JSON object [json] *)

val combine : t -> t -> t
(** Combine two JSON Objects together *)

Expand All @@ -90,6 +101,15 @@ val map : (t -> t) -> t -> t
(** [map f arr] calls the function [f] on each element of the JSON array
[arr], and returns a JSON array containing the results. *)

val assoc_map : (string * t -> t) -> t -> t
(** [assoc_map f json] calls the function [f] on each [(key, value)] pair of
the JSON object [json], and returns a JSON object containing the updated
[(key, f (key, value))]. *)

val assoc_map_filter : (string * t -> t option) -> t -> t
(** Same as [assoc_map] but filters the output of [f].
*)

val to_assoc : t -> (string * t) list
(** Extract the items of a JSON object or raise [Type_error]. *)

Expand Down