It should be, though it would be nice if browsers let you do enctype=json (and maybe enctype=xml). Json is popular enough at this point that you're more likely to have a high performance, easy to use codec library on the backend vs. FormData.
Form validation probably should have also been done via child tags, not attributes, so that error messages could be independently associated to each validation rule.
Lots of things could be improved about forms, but save for a few new field types tacked on, they've pretty much been left to rot. They kicked around a discussion of a json enclosure type at the W3C a decade ago and nothing came of it. I'll save the salty comments about W3C in general, and say either WHATWG implements it, or we're stuck with JS submissions for good.
If you use the same controller code for both the front-end and the back-end you can (along with, eg, browser-express and express and parallel GraphQL middleware for each execution context) use form posts for the HTML requests along with fetch for the SPA "requests".
This also means that your application will work the same with JS disabled as it does with JS enabled.
Here's a somewhat convoluted explanation of the general approach: https://fex-template.fly.dev - it happens to use F# with the Fable compiler but it should be somewhat legible to most developers!