I have designed a layered JSON system where each layer overrides or adds values to the previous JSON. Currently, I have defined a base entity, followed by one definition for each entity type, then the most specific data is provided at run time when the entity is created. As I was writing this system, it occurred to me that I could write my unit upgrades in the same JSON and just apply it. So much is possible: reloading these JSON definitions on the fly, tying in the entity editor, and even networking. Everything is coming together, and I'm loving it. Now to actually implement what I set out to do: tooltips. That is my next step.
While implementing this JSON system, I came across a few issues. First was that fastJSON didn't really want to deserialize to a generic placeholder object where I could apply the layers of JSON one after the other. I am glad I gave Json.NET a try, if for nothing else than the JObject and its collection initializer. It really helps to write C# code that looks like JSON instead of writing out a string that contains JSON data.
The second issue was a humorous fail cascade that caused the starting Solar Station to instantly disappear as the game started. You couldn't select it, so it wasn't a sprite issue. The creation code was executing, and all the right components were being created. You also couldn't press Esc to get the in-game menu to pop up, odd. After some digging, I found out that it thought the game was over, which is normal if there's no power producers in the game. Since it thought the game was over, it thought the in-game "game over" screen was already up and wouldn't let me press Esc. Mystery one solved. So my solar station was being deleted, but why? With some more digging, the Armour was zero, so the game thought it ran out of health and deleted it automatically. The JSON showed a non-zero value for Armour, and it was loading, or at least it was being set. The setter for the Armour field had a bounds check that made sure it was 0 <= Armour <= TotalArmour. Oi! My TotalArmour was zero, at least for a brief moment while the Armour was being set. *Sigh* A setter designed to prevent invalid values can really throw a wrench. After loosening the setter's rules, everything started working as intended.