///|
/// An ordered JSON document: object entries keep their order and duplicates,
/// numbers keep serde_json's classification. This is the input serde's
/// derived deserializers observe.
pub(all) enum Content {
Null
Bool(Bool)
Number(Number)
String(String)
Array(Array[Content])
Object(Array[Entry])
/// A value whose error serde_json reports only when the value is visited
/// (produced by lenient parsing; skipped values are accepted).
Invalid(ParseError)
/// A serialized `f32`: written with the shortest `f32` digits, like
/// serde_json's `serialize_f32`. As a `Value` it widens to `f64`, like
/// `serde_json::to_value`.
Float32(Float)
} derive(Debug, Eq)
///|
/// An object entry; `key_escaped` records whether the key's source text
/// contained escape sequences (it matters for serde_json's numeric map keys).
pub(all) struct Entry {
key : String
key_escaped : Bool
/// A deferred error in the key text (lenient parsing).
key_error : ParseError?
value : Content
} derive(Debug, Eq)
///|
/// The serde_json `Value` of a document (duplicate keys: the last wins; keys
/// sorted).
pub fn Content::to_value(self : Content) -> Value raise ParseError {
match self {
Invalid(e) => raise e
Float32(f) =>
match Number::from_f64(f.to_double()) {
Some(n) => Number(n)
None => Null
}
Null => Null
Bool(b) => Bool(b)
Number(n) => Number(n)
String(s) => String(s)
Array(xs) => {
let out = []
for x in xs {
out.push(x.to_value())
}
Array(out)
}
Object(entries) => {
let o = @collections.StrMap::new()
for e in entries {
if e.key_error is Some(err) {
raise err
}
o.set(e.key, e.value.to_value())
}
Object(o)
}
}
}
///|
/// The ordered document of a `Value` (keys in sorted order).
pub fn Value::to_content(self : Value) -> Content {
match self {
Null => Null
Bool(b) => Bool(b)
Number(n) => Number(n)
String(s) => String(s)
Array(xs) => Array(xs.map(x => x.to_content()))
Object(o) => {
let entries = []
for k, v in o {
entries.push({
key: k,
key_escaped: false,
key_error: None,
value: v.to_content(),
})
}
Object(entries)
}
}
}
///|
/// Compact JSON text of a document, identical to serde_json's serializer
/// (entries in order, duplicates preserved).
pub fn Content::to_string(self : Content) -> String {
let buf = StringBuilder()
write_content(buf, self)
buf.to_string()
}
///|
pub impl Show for Content with fn output(self, logger) {
logger.write_string(self.to_string())
}
///|
fn write_content(buf : StringBuilder, c : Content) -> Unit {
match c {
Null => buf.write_string("null")
Bool(b) => buf.write_string(if b { "true" } else { "false" })
Number(n) => buf.write_string(n.to_string())
Float32(f) =>
buf.write_string(
if f.is_nan() || f.is_inf() {
"null"
} else {
format_f32(f)
},
)
String(s) => write_escaped_str(buf, s)
Array(xs) => {
buf.write_char('[')
for i, x in xs {
if i > 0 {
buf.write_char(',')
}
write_content(buf, x)
}
buf.write_char(']')
}
Invalid(_) => buf.write_string("null")
Object(entries) => {
buf.write_char('{')
for i, e in entries {
if i > 0 {
buf.write_char(',')
}
write_escaped_str(buf, e.key)
buf.write_char(':')
write_content(buf, e.value)
}
buf.write_char('}')
}
}
}