Skip to content

Typed Document

Liu.Yandong.Hanks edited this page Aug 20, 2026 · 4 revisions

类型文档(TDoc)

Typed Document (TDoc)

适用版本:4.0.0

Applies to 4.0.0.

首页 · 脚本 TDoc API · .NET TDoc API

Home · Script TDoc API · .NET TDoc API

介绍

Introduction

TDoc 是 AuroraScript 的带类型文本数据格式。它将一个 AuroraScript 值写成独立文档,并在读取时恢复普通对象、数组、Packed Array、DatePathRegexHashMapStringBuffer 与宿主已注册的 CLR/CIL 对象。

TDoc is AuroraScript's typed text-data format. It writes one AuroraScript value as a standalone document and restores ordinary objects, arrays, packed arrays, Date, Path, Regex, HashMap, StringBuffer, and host-registered CLR/CIL objects when read.

TDoc 不是第二套脚本语法:文档内容不会执行代码,也不支持变量、函数调用、脚本 tdoc 标记或内联表达式。独立文档从根值直接开始。

TDoc is not a second scripting syntax: document content does not execute code and does not support variables, calls, the script tdoc marker, or inline expressions. A standalone document starts directly with its root value.

用途

Use Cases

  • 保存需要保留 AuroraScript 类型身份的配置、快照或持久化状态。

    Persist configuration, snapshots, or state that must retain AuroraScript type identity.

  • 在同一 AuroraScript 宿主之间交换数据,并且需要保留 Packed Array 或 Date 等类型。

    Exchange data between AuroraScript hosts when types such as packed arrays or Date must be preserved.

  • 将经 AuroraEngine.RegisterType 明确注册的 CLR/CIL 对象写入受控数据契约。

    Write CLR/CIL objects explicitly registered through AuroraEngine.RegisterType into a controlled data contract.

TDoc 不会将运行时行为当成持久化数据。写入时,函数、代理、访问器属性、未注册 CLR/CIL 对象、非有限 Number,以及已在当前文档中出现过的循环/共享引用都会按“可跳过值”处理,而不是使整个 stringify 失败。

TDoc does not treat runtime behavior as persistent data. When writing, functions, proxies, accessor properties, unregistered CLR/CIL objects, non-finite Numbers, and circular/shared references already seen in the current document are treated as skippable values rather than failing the entire stringify.

快速示例

Quick Example

Object {
    readonly String id "u-001",
    String name "Aurora",
    Number version 4,
    Int8Array payload [-128, 0, 127],
    Date createdAt "2026-08-20 10:00:00",
}

上面的文档根值是 ScriptObjectid 是浅只读属性,payload 保持为 ScriptInt8Array,而不是一般 Array

The root value above is a ScriptObject; id is a shallow read-only property and payload remains a ScriptInt8Array, rather than becoming a general Array.

脚本中使用 TDoc

Use TDoc in scripts:

var profile = TDoc.parse('Object { String name "Aurora", Int8Array levels [1, 2] }');
var text = TDoc.stringify(profile, false);
return text;

宿主中使用 AuroraTypedDocument

Use AuroraTypedDocument in a host:

var tdoc = new AuroraTypedDocument(engine);
var text = tdoc.Serialize(ScriptDatum.FromString("Aurora"));
var value = tdoc.Deserialize(text);

对象视图与可跳过值

Object View and Skippable Values

普通 ScriptObject 会按脚本可见的可枚举属性写入:先取自身属性,再沿 prototype 链取未被遮蔽的属性。写入后的 TDoc 是一个扁平对象;prototype 身份、原型链和访问器本身不会保留。

An ordinary ScriptObject is written from its script-visible enumerable properties: own properties first, then unshadowed properties along its prototype chain. The resulting TDoc is a flat object; prototype identity, the prototype chain, and accessors themselves are not preserved.

stringify 遇到不可表示的运行时值时采用固定的无异常降级规则:对象属性(包括从 prototype 看到的属性)会被省略;数组元素会写为 null 以保持索引;HashMap 条目中的不可表示键或值会写为 null;根值不可表示时结果为 null。因此 TDoc 是数据快照,不是完整对象图的保真克隆。

stringify uses fixed, non-throwing degradation for unrepresentable runtime values: object properties (including properties visible through a prototype) are omitted; array elements become null to preserve indices; an unrepresentable key or value in a HashMap entry becomes null; and an unrepresentable root becomes null. TDoc is therefore a data snapshot, not a lossless clone of a full object graph.

var action = () => true;
var value = { name: "Aurora", cancel: action, values: [1, action, 3] };
TDoc.stringify(value, false);
// {name "Aurora",values [1,null,3,],}

文本结构

Text Structure

一个文档只允许一个根值。类型名可显式写出;未写出时,只有原始字面量可唯一确定的类型会自动推断。

A document permits one root value. A type name may be explicit; when it is absent, only values uniquely determined by their raw literal are inferred automatically.

document      = typed-value EOF ;
typed-value   = [ type-name ] raw-value ;
raw-value     = "null" | boolean | number | string | array | object ;
array         = "[" [ typed-value { "," typed-value } [ "," ] ] "]" ;
object        = "{" [ member { "," member } [ "," ] ] "}" ;
member        = [ "readonly" ] [ type-name ] property-name raw-value ;
property-name = identifier | string ;
type-name     = identifier ;

对象成员中,两个连续标识符表示“类型名 + 属性名”;只有一个标识符时,它是属性名。例如 String name "Aurora" 显式声明 String,而 name "Aurora" 让读取器推断字符串。

In an object member, two consecutive identifiers mean “type name + property name”; one identifier is the property name. For example, String name "Aurora" explicitly declares String, while name "Aurora" lets the reader infer a string.

字符串值必须使用单引号或双引号。Object { id UX01 }Object { id UX01-03 } 都无效:前者中的 UX01 是标识符位置,后者的 - 也不属于标识符。请写为 Object { id "UX01" }Object { id "UX01-03" }

String values must use single or double quotes. Object { id UX01 } and Object { id UX01-03 } are both invalid: UX01 is in an identifier position in the former, and - is not part of an identifier in the latter. Write Object { id "UX01" } or Object { id "UX01-03" } instead.

支持 // 行注释、/* ... */ 块注释和尾逗号。脚本 tdoc 标记在独立文档中无效并会产生语法错误。

Line comments (//), block comments (/* ... */), and trailing commas are supported. The script tdoc marker is invalid in standalone documents and produces a syntax error.

类型与推断

Types and Inference

文本形状 读取结果 默认是否输出类型名
null Null
true / false Boolean
42 / 1.5 / 0xFF Numberdouble
"text" / 'text' String
[ ... ] ScriptArray
{ ... } ScriptObject
StringBuffer "text" StringBuffer
Date "..." / Date 14425655658 ScriptDate
Regex { ... } ScriptRegex
Path "a/b.as" ScriptPathValue
HashMap [[key, value]] ScriptHashMap
Int32Array / Int8Array / Float64Array / BooleanArray 对应 Packed Array 始终是
已注册类型,例如 User { ... } 已注册 CLR/CIL 实例 始终是

The table lists read results and whether a type name is emitted by default.

默认 EmitTypeNamesfalse,写入器仅输出无法由原始字面量唯一推断的类型名。ObjectArrayStringNumberBoolean 默认省略;Date、所有对象形内置类型、所有 Packed Array 和注册 CLR/CIL 类型仍强制输出类型名。将 EmitTypeNames 设为 true 可强制输出所有可用类型名。

EmitTypeNames defaults to false, so the writer emits only type names that cannot be uniquely inferred from raw literals. Object, Array, String, Number, and Boolean are omitted by default; Date, all object-like built-ins, all packed arrays, and registered CLR/CIL types still force a type name. Set EmitTypeNames to true to force every available type name.

// default: EmitTypeNames = false
{ name "Aurora", Int8Array bytes [1, 2] }

// EmitTypeNames = true
Object { String name "Aurora", Int8Array bytes [1, 2] }

readonly 属性

readonly Properties

readonly 是对象属性描述符,不是类型。它使该属性不能再次写入,但不会冻结其对象值。

readonly is an object-property descriptor, not a type. It prevents the property from being written again, but does not freeze its object value.

Object {
    readonly Object settings { retries 3 },
}

读取后 settings = other 会失败,而 settings.retries = 4 仍然可以执行。TDoc 写入器会保留 readonly 标记。

After reading, settings = other fails, while settings.retries = 4 remains valid. The TDoc writer preserves the readonly marker.

Date、Regex 与 HashMap

Date, Regex, and HashMap

Date 的字符串形式必须匹配当前 AuroraEngineEngineOptions.Runtime.DateTimeFormat;数值形式是 .NET ticks,必须是有效整数范围。写入时始终按引擎日期格式输出字符串。

A Date string must match the current AuroraEngine EngineOptions.Runtime.DateTimeFormat; a numeric form is .NET ticks and must be an in-range integer. Writing always produces a string using the engine date format.

Date "2026-08-20 10:00:00"
Regex { pattern "ab+", flags "gi" }
HashMap [["name", "Aurora"], [1, true]]

HashMap 使用二元数组保存键和值,因此非字符串键不会降级为对象属性。

HashMap uses two-element arrays for keys and values, so non-string keys do not degrade into object properties.

CLR/CIL 类型边界

CLR/CIL Type Boundary

文档中的 CLR/CIL 类型名必须是当前引擎已经注册的别名。TDoc 不会根据程序集名、.NET 类型名或反射自动加载类型。

A CLR/CIL type name in a document must be an alias already registered on the current engine. TDoc never auto-loads a type from an assembly name, .NET type name, or reflection.

engine.RegisterType<User>("User");
var tdoc = new AuroraTypedDocument(engine);
var user = tdoc.Deserialize("User { String Name \"Hanks\", Number Age 18 }");

读取时,未注册对象的显式别名、未知别名、不可构造类型和不符合注册成员契约的文本都会失败;写入时,未注册或不可写入的 CLR/CIL 值按可跳过值规则处理。即使 EmitTypeNamesfalseUser 这类已注册类型名也不会被省略。

When reading, an explicit alias for an unregistered object, an unknown alias, a non-constructible type, or text that violates the registered member contract fails. When writing, an unregistered or non-writable CLR/CIL value follows the skippable-value rules. A registered type name such as User is never omitted, even when EmitTypeNames is false.

错误与诊断

Errors and Diagnostics

宿主 API 会抛出 TypedDocumentException。其中 SourceNameLineColumnDataPath 用于定位错误;例如 $.meta.tags[2] 表示嵌套数组中的第三项。

Host APIs throw TypedDocumentException. Its SourceName, Line, Column, and DataPath locate the error; for example, $.meta.tags[2] identifies the third item in a nested array.

脚本 API 将该异常转换为 AuroraRuntimeException,消息以 TDoc.parse error:TDoc.stringify error: 开头。

The script API converts this exception to AuroraRuntimeException, with a message starting with TDoc.parse error: or TDoc.stringify error:.

相关 API

Related APIs

Clone this wiki locally