///|
/// JSON utilities for gateway API — built on top of the standard Json type.
///|
/// Parse a JSON string. Returns None for invalid input.
pub fn parse_json(s : String) -> Json? {
let result = @json.parse(s) catch { _ => return None }
Some(result)
}
///|
let max_safe_json_int64 : Int64 = 9007199254740991L
///|
let max_safe_json_number : Double = 9007199254740991.0
///|
fn is_json_safe_int64(value : Int64) -> Bool {
value <= max_safe_json_int64 && value >= 0L - max_safe_json_int64
}
///|
fn number_to_safe_int64(n : Double) -> Int64? {
if n > max_safe_json_number || n < 0.0 - max_safe_json_number {
return None
}
let value = n.to_int64()
if value.to_double() == n {
Some(value)
} else {
None
}
}
///|
fn parse_int64_string(s : String) -> Int64? {
let result : Result[Int64, _] = try? @string.parse_int64(s)
match result {
Ok(value) => Some(value)
Err(_) => None
}
}
///|
/// Convert an Int64 ID to JSON without losing precision for large IDs.
fn int64_id_to_json(value : Int64) -> Json {
if is_json_safe_int64(value) {
value.to_double().to_json()
} else {
value.to_string().to_json()
}
}
///|
/// Extract a vector (Array[Double]) from a JSON array
pub fn json_to_vector(json : Json) -> Array[Double]? {
match json {
Array(arr) => {
let result : Array[Double] = []
for item in arr {
match item {
Number(n, ..) => result.push(n)
_ => return None
}
}
Some(result)
}
_ => None
}
}
///|
/// Convert a vector to JSON array
pub fn vector_to_json(vec : Array[Double]) -> Json {
Json::array(vec.map(fn(n) { n.to_json() }))
}
///|
/// Convert Attrs to Json
pub fn attrs_to_json(attrs : @types.Attrs) -> Json {
@codec.attrs_to_json_value(attrs)
}
///|
/// Convert AttrValue to Json
pub fn attr_value_to_json(value : @types.AttrValue) -> Json {
@codec.attr_value_to_json(value)
}
///|
/// Convert Json to AttrValue
pub fn json_to_attr_value(json : Json) -> @types.AttrValue? {
@codec.json_to_attr_value(json)
}
///|
/// Convert Json (object) to Attrs
pub fn json_to_attrs(json : Json) -> @types.Attrs? {
@codec.json_to_attrs(json)
}
///|
/// Get a string field from a JSON object
pub fn get_string(obj : Json, key : String) -> String? {
match obj {
Object(m) =>
match m.get(key) {
Some(String(s)) => Some(s)
_ => None
}
_ => None
}
}
///|
/// Get a number field from a JSON object
pub fn get_number(obj : Json, key : String) -> Double? {
match obj {
Object(m) =>
match m.get(key) {
Some(Number(n, ..)) => Some(n)
_ => None
}
_ => None
}
}
///|
/// Get an integer field from a JSON object
pub fn get_int(obj : Json, key : String) -> Int? {
match obj {
Object(m) =>
match m.get(key) {
Some(Number(n, ..)) => Some(n.to_int())
_ => None
}
_ => None
}
}
///|
/// Get an Int64 field from a JSON object
pub fn get_int64(obj : Json, key : String) -> Int64? {
match obj {
Object(m) =>
match m.get(key) {
Some(Number(n, ..)) => Some(n.to_int64())
_ => None
}
_ => None
}
}
///|
/// Get a JSON API ID field.
///
/// Numeric IDs are accepted only when they are exactly representable as a JSON
/// number. Large Int64 IDs must be sent as strings.
fn get_int64_id(obj : Json, key : String) -> Int64? {
match obj {
Object(m) =>
match m.get(key) {
Some(Number(n, ..)) => number_to_safe_int64(n)
Some(String(s)) => parse_int64_string(s)
_ => None
}
_ => None
}
}
///|
/// Get a boolean field from a JSON object
pub fn get_bool(obj : Json, key : String) -> Bool? {
match obj {
Object(m) =>
match m.get(key) {
Some(True) => Some(true)
Some(False) => Some(false)
_ => None
}
_ => None
}
}
///|
/// Get an array field from a JSON object
pub fn get_array(obj : Json, key : String) -> Array[Json]? {
match obj {
Object(m) =>
match m.get(key) {
Some(Array(arr)) => Some(arr)
_ => None
}
_ => None
}
}
///|
/// Get an object field from a JSON object
pub fn get_object(obj : Json, key : String) -> Map[String, Json]? {
match obj {
Object(m) =>
match m.get(key) {
Some(Object(o)) => Some(o)
_ => None
}
_ => None
}
}
///|
/// Build a JSON object from key-value pairs
pub fn json_object(pairs : Array[(String, Json)]) -> Json {
let obj : Map[String, Json] = {}
for pair in pairs {
let (key, value) = pair
obj[key] = value
}
Json::object(obj)
}
///|
/// Build a JSON array
pub fn json_array(items : Array[Json]) -> Json {
Json::array(items)
}