Notes from @csala:
Maybe the validate call should be implicit instead of explicit when validating a JSON file?
In other words: Does it make sense to allow the user to run MetaData.from_json and reach the point where they have an "alive" metadata instance if the metadata that it contains is not valid?
IMO it does not make sense, which means that from_json should already call validate internally and crash right away if the given metadata is not valid.
Alternatively, maybe the validate should be classmethod (current instance method validate could be renamed to _validate), so one can run MetaData.validate(path_to_json_or_dict) and have their metadata validated without getting anything in return other than an exception if it is not valid.
I would also add a specific ValidationError and add nice user-friendly messages that explain why the metadata is not valid instead of using plain assert ....
Notes from @csala: