Root
Overview
This page covers the entry structure of the document loading layer:
root.jsontop-level structurevariants[]whenexpressionEnvironmentUnit and font-size conversion
This page does not cover asset field details, nor view/layout/style/props. See those separately in Assets, View, Layout, Placement.
Root Document Top-Level Structure
root.json must be a JSON object.
Example:
{
"version": "0.1.0",
"assets": [
"../../shared/constants/base.json",
"flows/main.json",
{
"type": "viewScreen",
"id": "home",
"children": []
}
],
"variants": [
{
"when": "${expr(${env.language} == \"zh\")}",
"assets": [
"../../shared/constants/i18n_zh.json",
{
"type": "constant",
"data": {
"hero": {
"title": "设置"
}
}
}
]
},
{
"when": "${expr(${env.widthDp} < 600dp)}",
"assets": [
"../../shared/constants/layout_phone.json",
"nodes/about.json",
"nodes/about_action_item.json"
]
}
]
}
Top-Level Field Table
Key |
Type |
Default |
Required |
Description |
|---|---|---|---|---|
|
string |
|
No |
Protocol version; currently |
|
array<string | object> |
|
No |
Shared resource list, processed in original order |
|
object[] |
|
No |
Condition-matched resource overlay list |
Top-Level Field Description
Version
type:
stringRequired: No
Current value:
"0.1.0"
Assets
type:
array<string | object>Required: No
Default: empty array
Notes:
Represents the shared resource list of the document
Each item can be: - a file path string - an embedded asset JSON object
The path resolves relative to the current
root.jsondirectoryRelative paths inside an embedded object also resolve against the current
root.jsondirectoryMay mix
constant/styleSet/imageSet/viewScreen/viewTemplate/interactionTemplate/screenFlowassetsWhen mixed, the array's original order applies strictly;
constants/nodes/screenFloware no longer root-level fields, put them inassets
Variants
type:
object[]Required: No
Default: empty array
Notes:
variantsmay be omitted or emptyWhen empty, only the top-level
assetsare loadedAll matched variants are overlaid; matching does not stop at the first hit
Variants[]
Each variant is a JSON object.
Example:
{
"when": "${expr(${env.language} == \"zh\" && ${env.widthDp} < 600dp)}",
"assets": [
"../../shared/constants/i18n_zh.json",
"../../shared/constants/layout_phone.json"
]
}
Field table:
Key |
Type |
Default |
Required |
Description |
|---|---|---|---|---|
|
string |
|
No |
Variant match condition; must be written as |
|
array<string | object> |
|
No |
Resources to overlay when the variant matches |
Assets Entry Forms
root.json.assets and variants[].assets both support two entry forms:
a path string
an embedded asset object
Example:
{
"version": "0.1.0",
"assets": [
"./constants/base.json",
{
"type": "viewScreen",
"id": "home_screen",
"children": []
}
]
}
Rules:
stringentry: - still denotes an external asset file pathobjectentry: - must be a valid asset object - must containtype- document standard types areconstant/styleSet/imageSet/viewScreen/viewTemplate/interactionTemplate/screenFlow-fontSet/themeare not documentassetsstandard types; register or load them through the Runtime global APIThe two entry forms can be mixed
The parser processes the array in original order and does not reorder by entry type
For relative paths inside
imageSet/viewScreen/viewTemplate/interactionTemplateembedded objects: - they resolve relative to the currentroot.jsondirectory
When Expression
Supported Environment References
${env.widthDp}${env.heightDp}${env.widthPx}${env.heightPx}${env.language}${env.theme}
Supported Operators
Comparison:
>,<,==,!=,>=,<=Logic:
&&,||,!Grouping:
(,)Arithmetic:
+,-,*,/String literal:
"zh"Numeric unit:
dp
Example
{ "when": "${expr(${env.language} == \"zh\")}" }
{ "when": "${expr(${env.theme} == \"shell.dark\")}" }
{ "when": "${expr(${env.widthDp} < 600dp)}" }
{ "when": "${expr(${env.widthDp} >= 600dp && ${env.heightDp} >= 360dp)}" }
{ "when": "${expr((${env.widthDp} >= 600dp && ${env.heightDp} >= 400dp) || ${env.widthPx} >= 1280)}" }
Runtime Environment
when must be written as ${expr(...)}, and the expression result must be a boolean, e.g. "${expr(${env.widthDp} < 600dp)}".
when evaluation relies on the Environment passed in by the caller.
See the current structure in
gui/brookesia_gui_interface/include/brookesia/gui_interface/document.hpp.
Main fields (defaults from document.hpp):
width_px: default320height_px: default480density: default1.0font_scale: default1.0language: default"zh"theme_id: default"default"colors:map<string, string>color table for${color.*}resolution; note it cannot be read via${env.*}
Conversion:
${env.widthDp} = width_px / density${env.heightDp} = height_px / density
These fields can also be referenced via ${env.*} in JSON resources. Currently supported: ${env.widthPx}, ${env.heightPx},
${env.widthDp}, ${env.heightDp}, ${env.density}, ${env.fontScale}, ${env.language} and
${env.theme}. ${env.widthDp} / ${env.heightDp} output an "Ndp" string, suitable for use within ${expr(...)}.
Environment is only responsible for:
whenexpression evaluationdp/spsize conversionProtocol inputs such as language and viewport
Recording the initial theme id;
${env.theme}inwhenuses this valueThe Runtime global
set_theme(...)is still the official entry for switching themes
If a document's variants[].when uses ${env.theme} or ${env.language}, the Runtime marks it as
environment-sensitive. set_theme(theme_id, true) / set_language(language, true) re-parse the root for file-backed documents,
so constants, images, and screen resources follow the variant update; non-file-backed documents can only reapply style and log a warning.
For theme resources and theme switching, see Runtime.
The view debug frame is not part of Environment but a Runtime-level debugging capability; see Runtime.
Unit and Font-Size Conversion
All sizes in JSON UI are converted to backend pixel values during parsing.
Basic concepts:
px- backend physical pixels - written as a JSON number in the protocol, e.g.24- the"24px"string suffix is not currently supporteddp- density-independent pixel - used for layout size, spacing, corner radius, borders, and other non-text sizes - formula:px = round(dp * Environment.density)sp- scale-independent pixel - used for font size - formula:px = round(sp * Environment.density * Environment.font_scale)fontSize- the public field name ofstyle.fontSize- semantically equivalent to thespfont size - the font size finally passed to the backend is the converted integer pixel value
Field rules:
layout.gaptakes adpstring or a bare numberpxplacement.x/placement.ytake adpstring, percentage, or bare numberpxplacement.width/placement.heightacceptdpstrings, percentages, bare numberspx,match,wrapstyle.borderWidth/style.radius/style.paddingtake adpstring or a bare numberpxstyle.fontSizetakes anspstring or a bare numberpxA bare number always means an already-converted
px; it is not multiplied bydensityorfont_scale
Example:
{
"placement": {
"width": "120dp",
"height": 48
},
"style": {
"padding": "12dp",
"fontSize": "20sp"
}
}
When Environment.density = 2.0 and Environment.font_scale = 1.2:
"120dp"->round(120 * 2.0) = 240px48->48px"12dp"->round(12 * 2.0) = 24px"20sp"->round(20 * 2.0 * 1.2) = 48px
Relationship between fontSize and native font resources:
a native font's
native_sizeis the pixel size of the generated fontthe backend selects a native font by the converted
fontSizepixel valueif there is no exact match, it picks the closest
native_sizeand logs a warning