Current section

Files

Jump to
ywt_core src ywt internal jose_json.gleam
Raw

src/ywt/internal/jose_json.gleam

import gleam/bit_array
import gleam/dynamic.{type Dynamic}
import gleam/dynamic/decode.{type Decoder}
import gleam/json
import gleam/result
/// Parse JOSE JSON with consistent duplicate member handling on all targets.
///
/// JavaScript's `JSON.parse` keeps the lexically last duplicate object member.
/// Erlang's default `json:decode/1` keeps the first, so the Erlang FFI uses
/// `json:decode/3` callbacks to match JavaScript.
@external(javascript, "../../../gleam_json/gleam/json.mjs", "parse")
pub fn parse(
from input: String,
using decoder: Decoder(value),
) -> Result(value, json.DecodeError) {
use dynamic_value <- result.try(
decode_to_dynamic(bit_array.from_string(input)),
)
decode.run(dynamic_value, decoder)
|> result.map_error(json.UnableToDecode)
}
@external(javascript, "../../../gleam_json/gleam/json.mjs", "parse_bits")
pub fn parse_bits(
from input: BitArray,
using decoder: Decoder(value),
) -> Result(value, json.DecodeError) {
use dynamic_value <- result.try(decode_to_dynamic(input))
decode.run(dynamic_value, decoder)
|> result.map_error(json.UnableToDecode)
}
@external(erlang, "ywt_core_ffi", "decode_json_to_dynamic")
@external(javascript, "../../../gleam_json/gleam_json_ffi.mjs", "decode")
fn decode_to_dynamic(input: BitArray) -> Result(Dynamic, json.DecodeError)