The DAQS Data Model
DAQS rules do not query Revit directly. They query the JSON file that DAQS Assist exports from the model.
Understanding how that JSON is organised prevents an entire category of mistakes.
Revit is hierarchical — DAQS is not
In Revit, data is nested. A Family contains Types, a Type contains Instances, an Instance belongs to a Level. You navigate this hierarchy in the UI by opening panels, clicking Edit Type, expanding trees.
DAQS exports this differently.
The DAQS JSON is a flat array. Every object — Family, Type, Instance, Level, Parameter — sits side by side in the same list.
[
{ "id": 617348, "type": "Family", "name": "Door wooden", ... },
{ "id": 617464, "type": "FamilySymbol", "name": "1018x2387", ... },
{ "id": 616521, "type": "FamilyInstance","name": "1018x2387", ... },
{ "id": 311, "type": "Level", "name": "00 begane grond", ... }
]
There is no nesting. A FamilyInstance does not contain its type's data.
A FamilySymbol does not contain a list of its instances.
Relationships are expressed by parent.id
Instead of nesting, DAQS uses references.
A FamilyInstance points to its FamilySymbol via parent:
{
"id": 616521,
"type": "FamilyInstance",
"parent": {
"id": 617464,
"type": "FamilySymbol"
}
}
A FamilySymbol points to its Family the same way:
{
"id": 617464,
"type": "FamilySymbol",
"parent": {
"id": 617348,
"type": "Family"
}
}
This is why DAQS is called relational — objects relate to each other through IDs, not through nesting.
What this means for rule writing
Data does not cascade down automatically
In Revit, when you select an instance, you can immediately open Type Properties and see the Assembly Code. The UI does this lookup for you.
In DAQS, you must do it yourself.
If you want to read assemblyCode while validating a FamilyInstance, you must:
- Find the
FamilyInstance - Read its
parent.idto get theFamilySymbolID - Look up the
FamilySymbolby that ID - Read
assemblyCodefrom the symbol'svalues
This is what two-step filtering is about.
Every rule starts with a type filter
Because everything is in one flat array, the first thing every rule does is narrow down to the relevant object type:
$[type = "FamilyInstance"]
$[type = "FamilySymbol"]
$[type = "Room"]
Without this, your query operates on the entire dataset.
The same structure, every time
Every object — regardless of type — follows the same shape:
{
"id": ...,
"type": "...",
"name": "...",
"parent": { "id": ..., "type": "..." } or null,
"values": { ... }
}
Once you know this shape, you can navigate any object in the dataset.
Why flat instead of nested?
A nested structure would mirror the Revit UI more closely, but it creates problems:
- An instance would need to embed its full type data — duplicated for every instance of that type
- Adding a new object type (like a
MechanicalSystem) would require a new nesting level - JSONata queries on deeply nested structures become complex and fragile
A flat, relational structure keeps every object independent and consistent. Rules stay predictable regardless of how complex the model is.
Next
For the detailed field-by-field reference of the JSON structure, see:
For how to navigate relationships between objects in filter expressions, see: