Accessing struct's variable parametrically on ESP8266
You can do it but it can be awkward. You'll need an array of structs, each member of which describes one member of your 'struct parameters' - essentially, an expansion of your present 'keys[]'.
Then you can consult this array randomly or in order to find the name, data-type, and memory offset of a given parameter (indexed by parameter order), or search it, to access the same information by parameter name.
Here's your parameter struct with some (incomplete but runnable) code to list the descriptor array, and incidentally, show how to build and use the array. Note that the code compiles but with a warning that a member of your 'parameters' was not initialized. I chose not to fix that; it isn't used here and doesn't prevent compilation.
struct parameters
{
  bool ext_inputs;
  bool auto_relay_off;
  bool useSerial;
  bool useWDT;
  bool useOTA;
  bool useResetKeeper;
  bool useFailNTP;
  bool useDebugLog;
  char deviceTopic[20];
  char groupTopic[20];
  char prefixTopic[20];
  int inputUpPin;
  int inputDownPin;
  int outputUpPin;
  int outputDownPin;
  int inputUpExtPin;
  int inputDownExtPin;
  int auto_relay_off_timeout;
};
//char *keys[] = {&quot;ext_inputs&quot;, &quot;auto_relay_off&quot;, &quot;useSerial&quot;, &quot;useWDT&quot;, &quot;useOTA&quot;, &quot;useResetKeeper&quot;,
//                &quot;useFailNTP&quot;, &quot;useDebugLog&quot;, &quot;deviceTopic&quot;, &quot;groupTopic&quot;, &quot;prefixTopic&quot;, &quot;inputUpPin&quot;,
//                &quot;inputDownPin&quot;, &quot;outputUpPin&quot;, &quot;outputDownPin&quot;, &quot;inputUpExtPin&quot;, &quot;inputDownExtPin&quot;,
//                &quot;auto_relay_off_timeout&quot;};

parameters def_par{false, false, false, true, true, false, true, &quot;devTopic&quot;, &quot;noGroup&quot;, &quot;myHome&quot;, 2, 1, 14, 12, 0, 2, 60};

parameters final_par;

// A couple of functions to extract data from an array or struct:
#define countof(a) (sizeof(a)/sizeof(a[0]))                             // ret # of array elements (not bytes)
#define offsetof(struc, member) ((int)(&amp;(((struc*)(0))-&gt;member)))   // ret byte-offset from start of struct to the given member

// Enumerate possible parameter types
typedef enum {
   t_bool, 
   t_char,
   t_int
} parType;

// Descriptor table - contains name, type, and offset of each parameter
// Could go in flash to save a bunch of RAM
struct descriptor {
   const char *name;
   parType pType;
   uint8_t offset;
} Descriptors[] = {
   { &quot;ext_inputs&quot;, t_bool, offsetof(parameters, ext_inputs) },
   { &quot;auto_relay_off&quot;, t_bool, offsetof(parameters, auto_relay_off) },
   // ...
   { &quot;inputUpPin&quot;, t_int, offsetof(parameters, inputUpPin) },
   // ...
   { &quot;auto_relay_off_timeout&quot;, t_int, offsetof(parameters, auto_relay_off_timeout) }
};

void setup() {
    Serial.begin(115200);
    Serial.println(&quot;parameter        type          offset\n&quot;);
    // List the parameters' names, types, and offsets within 'struct parameters'
    for( uint8_t i = 0;  i &lt; countof(Descriptors);  ++i ){
        Serial.print(Descriptors[i].name);    Serial.print(&quot;, &quot;);
        Serial.print(Descriptors[i].pType);   Serial.print(&quot;, &quot;);
        Serial.println(Descriptors[i].offset);
    }
}

void loop(){
    ;
}