aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2022-01-09 22:32:31 +0000
committerLouis Pilfold <louis@lpil.uk>2022-01-09 22:32:31 +0000
commit07d4c5e55453450013a0e398b9cc85e13c27d10d (patch)
tree79e309880b1620d6525fed29bdc0c1f876f0c262
parent850d26eaaf1c3de9bed14b249b406b19e3b437a4 (diff)
downloadgleam_json-07d4c5e55453450013a0e398b9cc85e13c27d10d.tar.gz
gleam_json-07d4c5e55453450013a0e398b9cc85e13c27d10d.zip
decode takes a dynamic decoder
-rw-r--r--README.md32
-rw-r--r--gleam.toml4
-rw-r--r--manifest.toml6
-rw-r--r--src/gleam/json.gleam24
-rw-r--r--test/gleam_json_test.gleam16
5 files changed, 46 insertions, 36 deletions
diff --git a/README.md b/README.md
index 9a0c9fc..8e6a35a 100644
--- a/README.md
+++ b/README.md
@@ -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)
}
```
diff --git a/gleam.toml b/gleam.toml
index a471dd0..609237b 100644
--- a/gleam.toml
+++ b/gleam.toml
@@ -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\"")