diff options
author | Louis Pilfold <louis@lpil.uk> | 2024-05-23 19:02:55 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2024-05-23 19:32:48 +0100 |
commit | 1979919b792910e6c75f3e28596f017d980b45ee (patch) | |
tree | e59fae108e195b6edc22bfc13181b2e2dcd7cd59 | |
parent | efe70ef04ae57bca78344cd13ccf4e40eac3ed21 (diff) | |
download | gleam_json-1979919b792910e6c75f3e28596f017d980b45ee.tar.gz gleam_json-1979919b792910e6c75f3e28596f017d980b45ee.zip |
Decoding
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | gleam.toml | 1 | ||||
-rw-r--r-- | src/gleam/json.gleam | 12 | ||||
-rw-r--r-- | src/gleam_json_ffi.erl | 12 | ||||
-rw-r--r-- | test/gleam_json_js_ffi_test.gleam | 10 | ||||
-rw-r--r-- | test/gleam_json_test.gleam | 21 |
7 files changed, 46 insertions, 23 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 702e391..84a7086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## v2.0.0 - Unreleased + +- The Thoas Erlang library has been removed as a dependency in favour of the + built-in Erlang JSON library. This means that Erlang/OTP 27.0 or higher is now + required. +- The `UnexpectedSequence` and `UnexpectedByte` error variants no longer have + labels for their arguments. + ## v1.0.1 - 2024-04-25 - Relaxed Thoas version requirement. @@ -2,11 +2,10 @@ Work with JSON in Gleam! -Under the hood library uses [Thoas](https://github.com/lpil/thoas/), the fastest -and most memory efficient pure Erlang JSON encoder/decoder. - ## Installation +Erlang/OTP 27.0 or higher is required when targeting Erlang. + Add this package to your Gleam project. ```shell @@ -2,6 +2,7 @@ name = "gleam_json" version = "1.0.1" gleam = ">= 0.32.0" +target = "javascript" licences = ["Apache-2.0"] description = "Work with JSON in Gleam" diff --git a/src/gleam/json.gleam b/src/gleam/json.gleam index 3c50712..9aadcda 100644 --- a/src/gleam/json.gleam +++ b/src/gleam/json.gleam @@ -1,16 +1,16 @@ -import gleam/list -import gleam/result import gleam/bit_array -import gleam/option.{type Option, None, Some} import gleam/dynamic.{type Dynamic} +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/result import gleam/string_builder.{type StringBuilder} pub type Json pub type DecodeError { UnexpectedEndOfInput - UnexpectedByte(byte: String, position: Int) - UnexpectedSequence(byte: String, position: Int) + UnexpectedByte(String) + UnexpectedSequence(String) UnexpectedFormat(List(dynamic.DecodeError)) } @@ -101,7 +101,7 @@ fn decode_to_dynamic(a: BitArray) -> Result(Dynamic, DecodeError) fn decode_to_dynamic(json: BitArray) -> Result(Dynamic, DecodeError) { case bit_array.to_string(json) { Ok(string) -> decode_string(string) - Error(Nil) -> Error(UnexpectedByte("", 0)) + Error(Nil) -> Error(UnexpectedByte("")) } } diff --git a/src/gleam_json_ffi.erl b/src/gleam_json_ffi.erl index c33f87f..2bfd6c6 100644 --- a/src/gleam_json_ffi.erl +++ b/src/gleam_json_ffi.erl @@ -6,7 +6,17 @@ ]). decode(Json) -> - thoas:decode(Json). + try + {ok, json:decode(Json)} + catch + error:unexpected_end -> {error, unexpected_end_of_input}; + error:{invalid_byte, Byte} -> {error, {unexpected_byte, hex(Byte)}}; + error:{unexpected_sequence, Byte} -> {error, {unexpected_sequence, Byte}} + end. + +hex(I) -> + H = list_to_binary(integer_to_list(I, 16)), + <<"0x"/utf8, H/binary>>. json_to_iodata(Json) -> Json. diff --git a/test/gleam_json_js_ffi_test.gleam b/test/gleam_json_js_ffi_test.gleam index cecfe20..b1ddb3b 100644 --- a/test/gleam_json_js_ffi_test.gleam +++ b/test/gleam_json_js_ffi_test.gleam @@ -39,7 +39,7 @@ pub fn chromium_unexpected_byte_test() { "Unexpected token a in JSON at position 5" |> StandardError |> get_json_decode_error("{\"b\":a}") - |> should.equal(UnexpectedByte(byte: "0x61", position: 5)) + |> should.equal(UnexpectedByte("0x61")) } @target(javascript) @@ -47,7 +47,7 @@ pub fn spidermonkey_unexpected_byte_test() { "JSON.parse: expected property name or '}' at line 1 column 6 of the JSON data" |> StandardError |> get_json_decode_error("{\"b\":a}") - |> should.equal(UnexpectedByte(byte: "0x61", position: 5)) + |> should.equal(UnexpectedByte("0x61")) } @target(javascript) @@ -55,7 +55,7 @@ pub fn javascript_core_unexpected_byte_test() { "JSON Parse error: Unexpected identifier \"a\"" |> StandardError |> get_json_decode_error("{\"b\":a}") - |> should.equal(UnexpectedByte(byte: "0x61", position: 0)) + |> should.equal(UnexpectedByte("0x61")) } @target(javascript) @@ -63,12 +63,12 @@ pub fn spidermonkey_multiline_unexpected_byte_test() { "JSON.parse: expected property name or '}' at line 2 column 6 of the JSON data" |> StandardError |> get_json_decode_error("{\n\"b\": a\n}") - |> should.equal(UnexpectedByte(byte: "0x61", position: 7)) + |> should.equal(UnexpectedByte("0x61")) "JSON.parse: expected double-quoted property name at line 3 column 1 of the JSON data" |> StandardError |> get_json_decode_error("{\n\"b\": \"x\",\na\n}") - |> should.equal(UnexpectedByte(byte: "0x61", position: 12)) + |> should.equal(UnexpectedByte("0x61")) } @target(javascript) diff --git a/test/gleam_json_test.gleam b/test/gleam_json_test.gleam index 3e22f00..fcc4a62 100644 --- a/test/gleam_json_test.gleam +++ b/test/gleam_json_test.gleam @@ -1,6 +1,7 @@ import gleam/dynamic import gleam/json.{type Json} import gleam/option.{None, Some} +import gleam/string import gleam/string_builder import gleeunit import gleeunit/should @@ -21,11 +22,8 @@ pub fn decode_empty_test() { pub fn decode_unexpected_byte_test() { let assert Error(error) = json.decode(from: "[}", using: dynamic.int) - let assert json.UnexpectedByte(byte, index) = error + let assert json.UnexpectedByte(byte) = error let assert "0x7D" = byte - - // V8 does not report the position of the unexpected byte any more. - let assert True = index == 1 || index == -1 } pub fn decode_unexpected_format_test() { @@ -45,11 +43,8 @@ pub fn decode_bits_empty_test() { pub fn decode_bits_unexpected_byte_test() { let assert Error(error) = json.decode(from: "[}", using: dynamic.int) - let assert json.UnexpectedByte(byte, index) = error + let assert json.UnexpectedByte(byte) = error let assert "0x7D" = byte - - // V8 does not report the position of the unexpected byte any more. - let assert True = index == 1 || index == -1 } pub fn decode_bits_unexpected_format_test() { @@ -57,6 +52,16 @@ pub fn decode_bits_unexpected_format_test() { |> should.equal(Error(json.UnexpectedFormat([empty_list_decode_error()]))) } +pub fn decode_unexpected_sequence_test() { + let assert Error(error) = + json.decode(from: "\"\\uxxxx\"", using: dynamic.float) + case error { + json.UnexpectedSequence("\\uxxxx") -> Nil + json.UnexpectedByte("0x78") -> Nil + _ -> panic as { "unexpected error: " <> string.inspect(error) } + } +} + pub fn encode_string_test() { json.string("hello") |> should_encode("\"hello\"") |