Reading the registers is a solved problem — pymodbus, libmodbus or any of a dozen libraries will hand you a list of 16-bit integers in about ten lines. The work is everything after that, because Modbus deliberately carries no semantics: register 40071 is a number, and what it means lives in a vendor PDF.
Four things have to be decided before the JSON is correct. Word order: a 32-bit value spans two registers and vendors disagree about which comes first, so the same bytes read as 1,250 or as 81,920,000. Signedness: a temperature below zero read as unsigned becomes 65,486. Scaling: many devices store 234 and mean 23.4, and SunSpec devices put the exponent in a separate register entirely. Units: the same register is watts on one firmware and kilowatts on the next.
So the honest answer is that you do not convert Modbus to JSON — you convert Modbus to JSON for a specific device, and that mapping is the artifact you end up maintaining. One register map per device model per firmware revision, forever.
The alternative is to normalize instead of transcribe: read the registers, hand the named values to a service that already holds the mappings, and get back canonical fields with a unit contract attached. Forge does that with 16,908 curated mappings, applying SunSpec scale factors and unit conversion on the way in, and rejecting values outside physics bounds rather than storing them.
You can produce syntactically valid JSON — {"40071": 234} — but it carries no meaning, no unit and no type, so nothing downstream can use it without the register map anyway. The mapping is not optional; the only choice is whether you maintain it or something else does.
SunSpec stores the exponent for a value in its own separate register. Read the value and skip the factor and you are wrong by a power of ten, and the result still looks like a plausible reading, so nothing alerts.
Yes. Big-endian and little-endian word order for 32-bit values are both common, and the Modbus specification does not settle it. Always verify against a known value rather than assuming.