Thank you for the reply. It does wholly make sense that the mod datapack overwrite the vanilla entry. Still feels weird though!
@thinkverse I don't know how adding custom loot to chests was done in 1.13, so I can't provide any particular "converting one method to another" insights. In 1.14.4, though, a LootTable object pretty much follows the same 'form' as a loot_tables JSON files, with pretty much the same naming. If you get a feel for how the JSON works, the LootTable object works pretty much the same way.
Generally, the LootTableLoadEvent will give you the LootTable object. To the LootTable, you add one or more LootPool objects. To each LootPool, you add one or more LootEntry. Annnd... to each LootEntry, one or more LootFunction. Each individual object will store the same bits of information as its corresponding block in the JSON. For example, the pool object has .rolls().
Each of the various objects do seem to have their own JSON deserializer, so it may even be possible to parse some mod-provided JSON and just add the result to the provided LootTable. I may spend some time going down this avenue at some point, but for now I'm very much in the "make it work so I can go back to being bad at creating textures" phase.