The validation of the JSON input files provided by the user is made possible by the getValue< ExpectedType > function and special keys and KeyPath s, as explained in Enhanced value access. This validator is customisable, i.e. the user can define a set of keys in their input file that will determine the behaviour of the validator under certain circumstances.

Validator options

The following keys of the mainJson object can be defined to customise the behaviour of the validator:

  • options.defaultValueUsedForMissingKey: determines the behaviour of the validator when the getValue( const nlohmann::json& j, const KeyPath& keyPath, const ValueType& defaultValue ) function is called and keyPath is undefined. By default, defaultValue is used without informing the user.
  • options.unusedKey: determines the behaviour of the validator when the void checkUnusedKeys( const nlohmann::json& mainJson, ... ) function is called and some of the keys defined in mainJson have not been accessed. This function is called by the json_interface application right before integrating the equations of motion, when all the settings objects have been created. By default, a warning is printed for each unused key.

These three options are converted to a value of the enum ExceptionResponseType defined in Tudat/JsonInterface/Support/errorHandling.h. The three possible values are:

  • continueSilently: allow this validator feature and do not inform the user.
  • printWarning: allow this validator feature but print a warning when using it.
  • throwError: do not allow this validator feature and terminate throwing an error when trying to use this feature. For defaultValueUsedForMissingKey, an UndefinedKeyError will be thrown (i.e. the behaviour of the getValue function with and without third default value argument will be equivalent). For unusedKey, the error message Validation failed because there are unused keys. will be printed after providing the list of unused keys.

Access history

The validator feature to check the keys that have not been used is useful to inform the user about the existence of redundant information in their input file, the use of old key identifiers that are not used anymore in the current version of Tudat, or the detection of typos in optional keys when manually writing the input file. Consider the following:

nlohmann::json j = { { "tyep", "euler" }, { "stepSize": 20 } };  // not typo in key "tyep"
std::string type = getValue( j, "type", "rungeKutta4" );

This would result in the integrator being used to be of the default type rungeKutta4 even though the intention of the user was to use of type euler. However, the user will not know about this unless they have configured the validator to warn about the use of default values (which is off by default). Thus, before integrating the equations of motion, when all the required information has been retrieved from the mainJson object, the call to checkUnusedKeys will print the following warning (by default):

Unused key: integrator.tyep

allowing the user to quickly identify and fix the problem. The validator can also be configured not to print a warning (this is highly discouraged) or to terminate in case that there are unused keys.

In order to make this feature possible, the json_interface has to keep track of all the key paths of mainJson that have been accessed, and then iterate over all its keys to check whether any of them has not been used. Keeping track of the accessed key paths is done by calling the getValue function (i.e. using the default value access methods will not keep track of the used keys). The original implementation proposal consisted in defining a special key, e.g. #accessedKeyPaths, for the mainJson object, in which an array of KeyPath s would be stored. However, the mainJson object is not always accessible in the from_json functions. For instance, in the following code it is accessible:

#include "integrator.h"

void from_json( const nlohmann::json& mainJson, Simulation& simulation )
    simulation.integrator =
      getValue< Integrator >( mainJson, "integrator" );  // integrators::from_json called

so the getValue function could potentially modify mainJson to add integrator as an accessed key, but here the mainJson object is not accessible:

namespace integrators
    void from_json( const nlohmann::json& jsonIntegrator, Integrator& integrator )
        integrator.type = getValue< std::string >( jsonIntegrator, "type" );
        integrator.stepSize = getValue< double >( jsonIntegrator, "stepSize" );

and thus is is not possible for the getValue to add the integrator.type and integrator.stepSize key paths to the mainObject’s #accessedKeyPaths special key.

A possible walk-around this issue could consist in defining the #accessedKeyPaths for each nlohmann::json object, and not only for the mainJson. However, the updated sub-nlohmann::json objects would still have to be passed back to the mainJson somehow. Even if this was possible, the definition of the from_json function, with the first argument as a const nlohmann::json& makes this approach unfeasible, as the getValue function would not be capable of updating it (it will not be possible to update its #accessedKeyPaths because it is a constant object). Thus, a completely different approach had to be followed, making use of a global variable. This global variable is declared in Tudat/JsonInterface/Support/valueAccess.h:

extern std::set< KeyPath > accessedKeyPaths;

This variable is automatically updated when calling the getValue function. In order to clear the contents of this variable, the function clearAccessHistory must be called. In the json_interface application, this is done after reading the input JSON file and just before starting to use the read nlohmann::json object to update the settings objects.


The current implementation has one limitation: it is not possible to keep track of the accessed keys of multiple nlohmann::json objects simultaneously. Currently, this is not done anywhere in the JSON Interface library, but if in the feature this is required, it will be necessary to create a derived class of nlohmann::json (e.g. EnhancedJSON) with the accessedKeyPaths as property and the functions getValue and checkUnusedKeys as methods (probably other global functions declared in Tudat/JsonInterface/Support/valueAccess.h would also have to be moved to this class). The to_json and from_json methods would have to be updated to take objects of this class as first argument instead of the basic nlohmann::json objects. An attempt to implement this was done at one point during the development of the json_interface, but it was unsuccessful due to the existence of an inheritance bug in the JSON library.