this repo has no description
1opam-version: "2.0" 2synopsis: "Elm-inspired decoders for Ocaml" 3description: """ 4A combinator library for "decoding" JSON-like values into your own Ocaml types, inspired by Elm's `Json.Decode` and `Json.Encode`. 5 6> Eh? 7 8An Ocaml program having a JSON (or YAML) data source usually goes something like this: 9 101. Get your data from somewhere. Now you have a `string`. 112. *Parse* the `string` as JSON (or YAML). Now you have a `Yojson.Basic.json`, or maybe an `Ezjsonm.value`, or perhaps a `Ocaml.yaml`. 123. *Decode* the JSON value to an Ocaml type that's actually useful for your program's domain. 13 14This library helps with step 3. 15 16## Getting started 17 18Install one of the supported decoder backends: 19 20``` 21opam install decoders-ezjsonm # For Ezjsonm 22opam install decoders-ocyaml # For Ocyaml 23opam install decoders-yojson # For Yojson 24npm install --save-dev bs-decoders # For Bucklescript 25``` 26 27Now we can start decoding stuff! 28 29First, a module alias to save some keystrokes. In this guide, we'll parse JSON 30using `Yojson`'s `Basic` variant. 31 32```ocaml 33utop # module D = Decoders_yojson.Basic.Decode;; 34module D = Decoders_yojson.Basic.Decode 35``` 36 37Let's set our sights high and decode an integer. 38 39```ocaml 40utop # D.decode_value D.int (`Int 1);; 41- : (int, error) result = Ok 1 42``` 43 44Nice! We used `decode_value`, which takes a `decoder` and a `value` (in this 45case a `Yojson.Basic.json`) and... decodes the value. 46 47```ocaml 48utop # D.decode_value;; 49- : 'a decoder -> value -> ('a, error) result = <fun> 50``` 51 52For convenience we also have `decode_string`, which takes a `string` and calls 53`Yojson`'s parser under the hood. 54 55```ocaml 56utop # D.decode_string D.int "1";; 57- : (int, error) result = Ok 1 58``` 59 60What about a `list` of `int`s? Here's where the "combinator" part comes in. 61 62```ocaml 63utop # D.decode_string D.(list int) "[1,2,3]";; 64- : (int list, error) result = Ok [1; 2; 3] 65``` 66 67Success! 68 69Ok, so what if we get some unexpected JSON? 70 71```ocaml 72utop # #install_printer D.pp_error;; 73utop # D.decode_string D.(list int) "[1,2,true]";; 74- : (int list, error) result = 75Error while decoding a list: element 2: Expected an int, but got true 76``` 77 78## Generic decoders 79 80 81Suppose our program deals with users and roles. We want to decode our JSON input 82into these types. 83 84```ocaml 85type role = Admin | User 86 87type user = 88 { name : string 89 ; roles : role list 90 } 91``` 92 93Let's define our decoders. We'll write a module functor so we can re-use the 94same decoders across different JSON libraries, with YAML input, or with 95Bucklescript. 96 97```ocaml 98module My_decoders(D : Decoders.Decode.S) = struct 99 open D 100 101 let role : role decoder = 102 string >>= function 103 | "ADMIN" -> succeed Admin 104 | "USER" -> succeed User 105 | _ -> fail "Expected a role" 106 107 let user : user decoder = 108 field "name" string >>= fun name -> 109 field "roles" (list role) >>= fun roles -> 110 succeed { name; roles } 111end 112 113module My_yojson_decoders = My_decoders(Decoders_yojson.Basic.Decode) 114``` 115 116Great! Let's try them out. 117 118```ocaml 119utop # open My_yojson_decoders;; 120utop # D.decode_string role {| "USER" |};; 121- : (role, error) result = Ok User 122 123utop # D.decode_string D.(field "users" (list user)) 124 {| {"users": [{"name": "Alice", "roles": ["ADMIN", "USER"]}, 125 {"name": "Bob", "roles": ["USER"]}]} 126 |};; 127- : (user list, error) result = 128Ok [{name = "Alice"; roles = [Admin; User]}; {name = "Bob"; roles = [User]}] 129``` 130 131Let's introduce an error in the JSON: 132 133```ocaml 134utop # D.decode_string D.(field "users" (list user)) 135 {| {"users": [{"name": "Alice", "roles": ["ADMIN", "USER"]}, 136 {"name": "Bob", "roles": ["SUPER_USER"]}]} 137 |};; 138- : (user list, error) result = 139Error 140 in field "users": 141 while decoding a list: 142 element 1: 143 in field "roles": 144 while decoding a list: 145 element 0: Expected a role, but got "SUPER_USER" 146``` 147 148We get a nice pointer that we forgot to handle the `SUPER_USER` role. 149 150## Release 151 152After updating CHANGES.md: 153 154``` 155npm version <newversion> 156dune-release tag 157dune-release -p decoders,decoders-ezjsonm,decoders-yojson 158```""" 159maintainer: "Matt Bray <matt@aestheticintegration.com>" 160authors: "Matt Bray <matt@aestheticintegration.com>" 161license: "ISC" 162homepage: "https://github.com/mattjbray/ocaml-decoders" 163doc: "https://mattjbray.github.io/ocaml-decoders/decoders-ezjsonm" 164bug-reports: "https://github.com/mattjbray/ocaml-decoders/issues" 165depends: [ 166 "ocaml" 167 "jbuilder" {>= "1.0+beta7"} 168 "ounit" {with-test} 169 "decoders" {< "0.3.0"} 170 "ezjsonm" {>= "0.4.0"} 171] 172build: [ 173 ["jbuilder" "build" "-p" name "-j" jobs] 174 ["jbuilder" "runtest" "-p" name "-j" jobs] {with-test} 175] 176dev-repo: "git+ssh://git@github.com/mattjbray/ocaml-decoders.git" 177url { 178 src: 179 "https://github.com/mattjbray/ocaml-decoders/releases/download/0.1.0/decoders-0.1.0.tbz" 180 checksum: [ 181 "sha256=291e46eab27e1c7d14b9dca366e37a0b54817ab1801dd60a565e7270fd3abb0a" 182 "md5=a97f370f3f7ff68d085ac01e05fab493" 183 ] 184}