aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2024-05-23 19:02:55 +0100
committerLouis Pilfold <louis@lpil.uk>2024-05-23 19:32:48 +0100
commit1979919b792910e6c75f3e28596f017d980b45ee (patch)
treee59fae108e195b6edc22bfc13181b2e2dcd7cd59
parentefe70ef04ae57bca78344cd13ccf4e40eac3ed21 (diff)
downloadgleam_json-1979919b792910e6c75f3e28596f017d980b45ee.tar.gz
gleam_json-1979919b792910e6c75f3e28596f017d980b45ee.zip
Decoding
-rw-r--r--CHANGELOG.md8
-rw-r--r--README.md5
-rw-r--r--gleam.toml1
-rw-r--r--src/gleam/json.gleam12
-rw-r--r--src/gleam_json_ffi.erl12
-rw-r--r--test/gleam_json_js_ffi_test.gleam10
-rw-r--r--test/gleam_json_test.gleam21
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.
diff --git a/README.md b/README.md
index 87d806b..3de4559 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/gleam.toml b/gleam.toml
index cfb5fca..e9304d8 100644
--- a/gleam.toml
+++ b/gleam.toml
@@ -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\"")