diff options
author | Louis Pilfold <louis@lpil.uk> | 2022-01-09 22:32:31 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2022-01-09 22:32:31 +0000 |
commit | 07d4c5e55453450013a0e398b9cc85e13c27d10d (patch) | |
tree | 79e309880b1620d6525fed29bdc0c1f876f0c262 | |
parent | 850d26eaaf1c3de9bed14b249b406b19e3b437a4 (diff) | |
download | gleam_json-07d4c5e55453450013a0e398b9cc85e13c27d10d.tar.gz gleam_json-07d4c5e55453450013a0e398b9cc85e13c27d10d.zip |
decode takes a dynamic decoder
-rw-r--r-- | README.md | 32 | ||||
-rw-r--r-- | gleam.toml | 4 | ||||
-rw-r--r-- | manifest.toml | 6 | ||||
-rw-r--r-- | src/gleam/json.gleam | 24 | ||||
-rw-r--r-- | test/gleam_json_test.gleam | 16 |
5 files changed, 46 insertions, 36 deletions
@@ -23,9 +23,9 @@ import gleam/json.{object, string, list, int, null} pub fn cat_to_json(cat: Cat) -> String { object([ #("name", string(cat.name)), - #("lives", int(9), + #("lives", int(cat.lives), #("flaws", null()), - #("nicknames", array(["Kitty", "Sweetie"], of: string)), + #("nicknames", array(cat.nicknames, of: string)), ]) |> json.to_string } @@ -39,27 +39,17 @@ JSON is decoded into a `Dynamic` value which can be decoded using the ```rust import myapp.{Cat} import gleam/json -import gleam/dynamic +import gleam/dynamic.{field, list, int, string} import gleam/result -pub fn cat_from_json(json: String) -> Result<Cat, MyError> { - try data = - json.decode(encoded) - |> result.map_error(InvalidJson) +pub fn cat_from_json(json_string: String) -> Result<Cat, json.DecodeError> { + let cat_decoder = dynamic.decode2( + Cat, + field("name", of: string), + field("lives", of: int), + field("nicknames", of: list(string)), + ) - let data = dynamic.from(data) - try cat = { - try name = dynamic.field(data, "name") - try name = dynamic.string(name) - Ok(Cat(name)) - } - |> result.map_error(InvalidFormat) - - Ok(cat) -} - -pub type MyError { - InvalidJson(json.DecodeError) - InvalidFormat(dynamic.DecodeError) + json.decode(from: json_string, using: cat_decoder) } ``` @@ -3,8 +3,6 @@ version = "0.2.0" licences = ["Apache-2.0"] description = "Work with JSON in Gleam" -# target = "javascript" - repository = { type = "github", user = "gleam", repo = "json" } links = [ { title = "Website", href = "https://gleam.run" }, @@ -12,7 +10,7 @@ links = [ ] [dependencies] -gleam_stdlib = "~> 0.18" +gleam_stdlib = "~> 0.19" thoas = "~> 0.2" [dev-dependencies] diff --git a/manifest.toml b/manifest.toml index d71063c..a406eb6 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,12 +2,12 @@ # You typically do not need to edit this file packages = [ - { name = "gleam_stdlib", version = "0.18.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "763ECD87D54D08755EE4C8551720D122FDCA47F61D1CA8AF23B19A90395A7468" }, - { name = "gleeunit", version = "0.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7FA7477D930178C1E59519DBDB5E086BE3A6B65F015B67DA94D30A323062154" }, + { name = "gleam_stdlib", version = "0.19.2", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "FFA79EA12369F122B68885E694E097D6810402A2F86BFF48AAE9E40ACE654F4C" }, + { name = "gleeunit", version = "0.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "77701A5E5A565727E1EEAC9196FB878D544049B6331CD0305B5A69699135EA1C" }, { name = "thoas", version = "0.2.0", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "630AAEE57FB3FDE201578E787259E15E788A27733D49DE8DCCE1354DB1885B8D" }, ] [requirements] -gleam_stdlib = "~> 0.18" +gleam_stdlib = "~> 0.19" gleeunit = "~> 0.5" thoas = "~> 0.2" diff --git a/src/gleam/json.gleam b/src/gleam/json.gleam index 7db916d..b94a1d4 100644 --- a/src/gleam/json.gleam +++ b/src/gleam/json.gleam @@ -11,6 +11,7 @@ pub type DecodeError { UnexpectedEndOfInput UnexpectedByte(byte: String, position: Int) UnexpectedSequence(byte: String, position: Int) + UnexpectedFormat(List(dynamic.DecodeError)) } /// Decode a JSON string into dynamically typed data which can be decoded into @@ -19,16 +20,31 @@ pub type DecodeError { /// ## Examples /// /// ```gleam -/// > decode("[1,2,3]") -/// Ok(dynamic.from([1, 2, 3])) +/// > decode("[1,2,3]", dynamic.list(of: dynamic.int)) +/// Ok([1, 2, 3]) /// ``` /// /// ```gleam -/// > decode("[") +/// > decode("[", into: dynamic.list(of: dynamic.int)) /// Error(UnexpectedEndOfInput) /// ``` /// -pub external fn decode(String) -> Result(Dynamic, DecodeError) = +/// ```gleam +/// > decode("1", into: dynamic.string) +/// Error(UnexpectedFormat([dynamic.DecodeError("String", "Int", [])])) +/// ``` +/// +pub fn decode( + from json: String, + using decoder: dynamic.Decoder(t), +) -> Result(t, DecodeError) { + try dynamic_value = decode_to_dynamic(json) + dynamic_value + |> decoder + |> result.map_error(UnexpectedFormat) +} + +external fn decode_to_dynamic(String) -> Result(Dynamic, DecodeError) = "gleam_json_ffi" "decode" /// Convert a JSON value into a string. diff --git a/test/gleam_json_test.gleam b/test/gleam_json_test.gleam index 7e93ab7..fb55c90 100644 --- a/test/gleam_json_test.gleam +++ b/test/gleam_json_test.gleam @@ -11,21 +11,27 @@ pub fn main() { } pub fn decode_test() { - json.decode("5") - |> result.map(dynamic.from) - |> should.equal(Ok(dynamic.from(5))) + json.decode(from: "5", using: dynamic.int) + |> should.equal(Ok(5)) } pub fn decode_empty_test() { - json.decode("") + json.decode(from: "", using: dynamic.int) |> should.equal(Error(json.UnexpectedEndOfInput)) } pub fn decode_unexpected_byte_test() { - json.decode("[}") + json.decode(from: "[}", using: dynamic.int) |> should.equal(Error(json.UnexpectedByte("0x7D", 1))) } +pub fn decode_unexpected_format_test() { + json.decode(from: "[]", using: dynamic.int) + |> should.equal(Error(json.UnexpectedFormat([ + dynamic.DecodeError(expected: "Int", found: "List", path: []), + ]))) +} + pub fn encode_string_test() { json.string("hello") |> should_encode("\"hello\"") |