Files
adf-codec/src/canonical-json.ts
T

30 lines
1.1 KiB
TypeScript

import type { JsonValue } from './json-value.ts'
export type JsonSpelling = 'compact' | 'two-space'
export function serializeCanonicalJson(value: JsonValue, spelling: JsonSpelling): string {
return serialize(value, spelling === 'compact' ? '' : ' ', 0)
}
function serialize(value: JsonValue, indent: string, depth: number): string {
if (Array.isArray(value)) {
if (value.length === 0) return '[]'
const items = value.map((item) => serialize(item, indent, depth + 1))
return `[${join(items, indent, depth)}]`
}
if (value !== null && typeof value === 'object') {
const keys = Object.keys(value).sort()
if (keys.length === 0) return '{}'
const separator = indent === '' ? ':' : ': '
const entries = keys.map((key) => `${JSON.stringify(key)}${separator}${serialize(value[key] ?? null, indent, depth + 1)}`)
return `{${join(entries, indent, depth)}}`
}
return JSON.stringify(value)
}
function join(parts: readonly string[], indent: string, depth: number): string {
if (indent === '') return parts.join(',')
const inner = `\n${indent.repeat(depth + 1)}`
return `${inner}${parts.join(`,${inner}`)}\n${indent.repeat(depth)}`
}