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)