Export format: the two kinds of file you can take away
This is the technical description of AquaLog's data portability (#1505): which files the app hands over, what is in them, and how other software reads them. It is written for two readers — someone moving their data elsewhere (or helping them), and a regulator checking that "portable" is more than a word. The Traditional Chinese version is the original; this is its translation.
Why portability is done by the app and not handed over by the operator is in Refunds, tax and data portability, section 3.
1. Full backup: ZIP
Settings → Backup, restore and data management → "Create full backup". No connection, no server; the file is made on the device and handed to you through the share sheet or a download.
aqualog-backup-YYYYMMDD-HHmm.zip
├── manifest.json description: format, version, size and SHA-256 of every file
├── data.json every structured record (UTF-8 JSON)
└── photos/ every original photo and receipt
└── <media-id>.<extension>
1.1 manifest.json
| Field | Content |
|---|---|
format | Always aqualog-backup |
formatVersion | The backup format version, currently 1 |
createdAt | When it was made, ISO 8601 (UTC) |
timezone | The device's IANA time zone when it was made, for example Asia/Hong_Kong |
appVersion | The app version that made the backup |
schemaVersion | The database schema version; within one formatVersion, tables are only ever added |
dataFile | { path: "data.json", byteSize, sha256 } |
photos | One entry per photo: mediaId, path, mimeType, extension, byteSize, width, height, sha256 |
counts | The number of records in each table |
totals | { fileCount, uncompressedBytes } |
SHA-256 values are lowercase hexadecimal. Any software can use them to check that a file was not damaged in transit.
1.2 data.json
| Field | Content |
|---|---|
format | Always aqualog-data |
formatVersion | The same as in the manifest |
schemaVersion | The same as in the manifest |
exportedAt | When it was exported, ISO 8601 (UTC) |
tables | An object; each key is a table name, each value the array of its records |
- Every record has a string
id(a UUID); a reference to another table is a…Idfield holding that record'sid, for examplepurchaseItems[].purchaseId. - Dates and times are ISO 8601 strings; amounts are numbers.
- Tables are added as the app grows (
schemaVersionincreases); existing tables are never removed or renamed. The complete list is the keys ofcounts, not copied into this document — a copy would drift. - Photo metadata is in
tables.media, matched to the files inphotos/byid/mediaId; the links between records and photos are intables.mediaLinks.
1.3 Photos
photos/<media-id>.<extension> is the original file, not recompressed. The extension follows the MIME type (jpg, png, webp, heic and so on).
1.4 Reading it
Any tool that opens ZIP and reads JSON can open it: a spreadsheet, Python (zipfile + json), or unzipping it and reading it in a text editor. AquaLog itself restores everything from this file.
2. Table export: CSV
Settings → Backup, restore and data management → "Category CSV export". Per-category exports for spreadsheets, without photos.
- File name:
AquaLog-<category>-<date>.csv - Encoding: UTF-8 with a BOM (so Excel reads Chinese correctly), CRLF line endings
- Column names and yes/no values are bilingual, "Chinese / English"
- A value starting with
=,+,-or@gets a leading single quote, so a spreadsheet does not run it as a formula
Categories:
| Category | Content |
|---|---|
fish | Fish |
plants | Plants |
invertebrates | Shrimp, snails and other invertebrates |
decorations | Hardscape and decorations |
purchases | Purchases |
feeding | Feeding |
water_changes | Water changes |
water_quality | Water tests |
maintenance | Maintenance |
3. Which one is "all my data"
The ZIP backup. The CSV files are a convenient subset. The synced copy on the server is ciphertext the operator cannot open, so it cannot hand over its content; it is not a source for portability — see Refunds, tax and data portability.
The field lists in this document are checked against the code by src/features/backup/exportFormat.doc.test.ts: one field more or fewer in the manifest or data.json, or a new CSV category, fails that test first.