The problem here is chicken and egg. When you import a content item from the content.json, it passes the plone.restapi deserialisation calls and also all validators are run. When you want to recreate a relation like on the related items, you need to instantiate and persist a RelationValue.
If the target content item you want to relate to hasn't been imported yet into the Plone site, you basically can't. The current solution is to have a 2 phase import: create the content tree in phase1, re-apply al relations in phase 2 when all content is there.
An alternative solution would be to store the relations in the content.json file, but make the import process smart by pushing al relations onto a queue in memory or a temporary annotation on the site root or wherever, and process the queue after all content has been imported. Still 2 phases, but store the relations in the content itself.
We could simplify the import for other 'metadata' values like the default page as well. There we have the same problem: if you try to set a content item as default page on a folder, but the content item itself hasn't been created yet in the folder, you can't set that default page.
If it's an import issue, then I can avoid it. (This makes me super sad, but I have a therapist).
The new CMS doesn't have the validation on import and the object's reference error is postponed until rendering (this referenced image isn't here: 404).
So, yes. My export can (and will) contain references. Thank you @fredvd for this insight.
In the transmogrifier days, we used to just import twice - ignoring the errors on the first round
But the "right" way to do it was to catch the validation error and annotate the pipeline to "try this guy again", and a source would pull in those for a second try. But who uses transmogrifier anymore?