It isn't hard: I've built several Serde impls for Rust that handle JSON-api and JSON-LD setups (for a.o. ActivityPub). It's just an Enum and a type with some logic to parse one or the other. An if/else isn't hard.
And it certainly is not the reason AP hasn't taken off. For one, because AP has taken off, and secondly because of all the reasons it would potentially not have taken off, the underlying dialect of JSON is the least of all concerns.
Maybe rust has a better typing system that can handle the union of MaybeSliceOfStrings|MaybeSliceOfObjects|MaybeString|MaybeObject|MaybeNull[1] types better than Go does, but I can tell you - after about 4-5 years of trying to implement a clean Go API for processing ActivityPub payloads that the complexity is quite high, at least if you want to build something that can work with more than one client/service.
[1] I believe that a good implementation should handle even mixed cases, where you have a slice of both objects and strings.
And I'm not familiar enough with large go setups, but generally -in any language- anything that must handle data "down the pipeline" should ideally not be bothered about whether this link (or meta, or paginator, or whatever) is there, is of Type-T and so on: that's for middleware/controllers etc to ensure, and to transform. In other words: your business-logic should ideally never have to bother about a link being either a string or a struct or a null etc: it should be able to assume it's a MyLink.
Also, I'm not sure I agree with your thesis that business logic needs to worry only about a single type of object, because the ActivityPub specification recognizes all of the types I mentioned in my first reply as being "valid" and if you consider their superset as being the "canonical type" you'll be wasting quite a lot of storage (memory and disk wise) when all you have access to is the plain URL.
I did some deep diving into RDF stuff not too long ago and all the FLOSS databases I found didn’t do json-ld but it also didn’t look all that hard to add. Just adapt the existing xml code methinks.
The main purpose for which I chose Go for the development of this project was simplicity of the build/deploy pipelines. My targets are small communities and single enthusiasts which shouldn't need a dedicated SRE to deploy a service in the Fediverse.