Skip to content

workouts: JSON keys diverge from CSV headers (startdate vs start, deviceid vs device_id, nested data{} vs flat columns) #27

@DTTerastar

Description

@DTTerastar

Severity

minor

Summary

Sibling of #20 but for the workouts subcommand. Cross-format consumers maintain two name maps and a flat-vs-nested shape difference.

Reproduce

HEAD b58068351a2edeb90f0d26b9098f04e85db225ee.

$ /tmp/qa-bin/withings-export workouts --since 90d --format csv | head -1
date,start,end,category,category_code,timezone,duration_min,eff_duration_min,calories,steps,distance_m,elevation_m,hr_avg,hr_min,hr_max,hr_zone_0,hr_zone_1,hr_zone_2,hr_zone_3,device_id

$ /tmp/qa-bin/withings-export workouts --since 90d --format json | jq '.[0] | keys'
[
  "attrib", "category", "data", "date", "deviceid",
  "enddate", "id", "model", "startdate", "timezone"
]

Drift:

CSV JSON
start startdate (epoch seconds)
end enddate (epoch seconds)
device_id deviceid
category (name string), category_code (int) category (int only)
duration_min, eff_duration_min, calories, steps, distance_m, elevation_m, hr_*, hr_zone_* (flat) data.{effduration, calories, steps, distance, elevation, hr_average, hr_min, hr_max, hr_zone_0..3, manual_distance, manual_calories, intensity, pause_duration, ...} (nested)
(none) attrib, id, model (extra metadata)

The prime text documents the JSON shape, so it's intentional in spirit, but the divergence with CSV is significant: a downstream tool can't pick one schema and use it for both. `measurements` and `activity` have only minor unit-suffix differences (distance_m/`distance`, `hr_avg`/`hr_average`); `workouts` is the most divergent.

Expected

Either:

  • Pick canonical field names per row and use them in both serializers (preferred — flat snake_case with unit suffixes, e.g. `device_id`, `start_epoch`, `category` (string), `category_code` (int)).
  • Or, document the mapping in `prime` (currently only the JSON shape is documented).

If the intent is to keep raw Withings shape in JSON and mapped/flat shape in CSV, prime should say so explicitly. (#20 covers the same problem for `intraday`.)

Metadata

Metadata

Assignees

Labels

area:format--format markdown/json/csv and codec behavior.kind:bugObserved behavior diverges from documented behavior.priority:mediumReproducible bug or gap with a workaround, or a well-scoped enhancement clearly in charter.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions