diff options
author | Louis Pilfold <louis@lpil.uk> | 2022-02-05 09:37:37 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2022-02-05 09:37:37 +0000 |
commit | 6821a758373686042096a3b54f39743532c32aaa (patch) | |
tree | 35993985463cd39b62807e34d8a59f39c276a87d | |
parent | ce5c3bbbd7f4ed811f9bbaadce05165fe483c4f6 (diff) | |
download | gleam_json-6821a758373686042096a3b54f39743532c32aaa.tar.gz gleam_json-6821a758373686042096a3b54f39743532c32aaa.zip |
decode_bits
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/gleam/json.gleam | 34 | ||||
-rw-r--r-- | test/gleam_json_test.gleam | 22 |
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`. @@ -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\"") |