aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--README.md4
-rw-r--r--src/gleam/json.gleam34
-rw-r--r--test/gleam_json_test.gleam22
4 files changed, 59 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 466f41d..c0be33c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## v0.4.0 - Unreleased
+
+- The `decode_bits` function has been added.
+
## v0.3.0 - 2022-01-09
- The `decode` function now takes a `gleam/dynamic.Decoder`.
diff --git a/README.md b/README.md
index 455ce08..dddcf6c 100644
--- a/README.md
+++ b/README.md
@@ -17,14 +17,14 @@ gleam add gleam_json
```rust
import myapp.{Cat}
-import gleam/json.{object, string, array, int, null}
+import gleam/json.{object, string, mapped_array, int, null}
pub fn cat_to_json(cat: Cat) -> String {
object([
#("name", string(cat.name)),
#("lives", int(cat.lives),
#("flaws", null()),
- #("nicknames", array(cat.nicknames, of: string)),
+ #("nicknames", mapped_array(cat.nicknames, of: string)),
])
|> json.to_string
}
diff --git a/src/gleam/json.gleam b/src/gleam/json.gleam
index b94a1d4..b19c121 100644
--- a/src/gleam/json.gleam
+++ b/src/gleam/json.gleam
@@ -1,6 +1,7 @@
import gleam/map
import gleam/list
import gleam/result
+import gleam/bit_string
import gleam/option.{None, Option, Some}
import gleam/dynamic.{Dynamic}
import gleam/string_builder.{StringBuilder}
@@ -38,13 +39,40 @@ pub fn decode(
from json: String,
using decoder: dynamic.Decoder(t),
) -> Result(t, DecodeError) {
+ let bits = bit_string.from_string(json)
+ decode_bits(bits, decoder)
+}
+
+/// Decode a JSON bit string into dynamically typed data which can be decoded
+/// into typed data with the `gleam/dynamic` module.
+///
+/// ## Examples
+///
+/// ```gleam
+/// > decode_bits(<<"[1,2,3]">>, dynamic.list(of: dynamic.int))
+/// Ok([1, 2, 3])
+/// ```
+///
+/// ```gleam
+/// > decode_bits(<<"[">>, into: dynamic.list(of: dynamic.int))
+/// Error(UnexpectedEndOfInput)
+/// ```
+///
+/// ```gleam
+/// > decode_bits("<<1">>, into: dynamic.string)
+/// Error(UnexpectedFormat([dynamic.DecodeError("String", "Int", [])]))
+/// ```
+///
+pub fn decode_bits(
+ from json: BitString,
+ using decoder: dynamic.Decoder(t),
+) -> Result(t, DecodeError) {
try dynamic_value = decode_to_dynamic(json)
- dynamic_value
- |> decoder
+ decoder(dynamic_value)
|> result.map_error(UnexpectedFormat)
}
-external fn decode_to_dynamic(String) -> Result(Dynamic, DecodeError) =
+external fn decode_to_dynamic(BitString) -> 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 fb55c90..6460e51 100644
--- a/test/gleam_json_test.gleam
+++ b/test/gleam_json_test.gleam
@@ -32,6 +32,28 @@ pub fn decode_unexpected_format_test() {
])))
}
+pub fn decode_bits_test() {
+ json.decode_bits(from: <<"5":utf8>>, using: dynamic.int)
+ |> should.equal(Ok(5))
+}
+
+pub fn decode_bits_empty_test() {
+ json.decode_bits(from: <<"":utf8>>, using: dynamic.int)
+ |> should.equal(Error(json.UnexpectedEndOfInput))
+}
+
+pub fn decode_bits_unexpected_byte_test() {
+ json.decode_bits(from: <<"[}":utf8>>, using: dynamic.int)
+ |> should.equal(Error(json.UnexpectedByte("0x7D", 1)))
+}
+
+pub fn decode_bits_unexpected_format_test() {
+ json.decode_bits(from: <<"[]":utf8>>, 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\"")