Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "GeneralUserObject.h" 13 : 14 : /** 15 : * User object that reads a JSON file and makes its data available to other objects 16 : */ 17 : class JSONFileReader : public GeneralUserObject 18 : { 19 : public: 20 : static InputParameters validParams(); 21 : 22 : JSONFileReader(const InputParameters & parameters); 23 : 24 : /// Required implementation of a pure virtual function (not used) 25 11 : virtual void initialize() override {} 26 : 27 : /// Required implementation of a pure virtual function (not used) 28 11 : virtual void finalize() override {} 29 : 30 : /// Read the file again 31 11 : virtual void execute() override { read(_filename); } 32 : 33 : /// Getters for single values 34 : /** 35 : * Get a value that is directly indexed at the root of the JSON file/tree 36 : * @param value_name the name of the desired value 37 : * @param value reference to the value that will be set with the value in the JSON 38 : */ 39 : template <typename T> 40 2 : void getValue(const std::string & value_name, T & value) const 41 : { 42 2 : if (!_root.contains(value_name)) 43 1 : mooseError("Attempted to get '", 44 : value_name, 45 : "' but the JSON file does not contain this key directly at the root level"); 46 1 : value = _root[value_name].get<T>(); 47 1 : } 48 : 49 : /** 50 : * Get a value in the JSON file/tree using the keys in the 'value_keys' one by one to 51 : * traverse the JSON tree down to the requested value 52 : * @param value_keys the keys in descending order to access the value 53 : * @param value reference to the value that will be set with the value in the JSON 54 : */ 55 : template <typename T> 56 2 : void getValue(const std::vector<std::string> & value_keys, T & value) const 57 : { 58 2 : if (!value_keys.size()) 59 1 : mooseError("There should be at least one key to retrieve a value from the JSON"); 60 : 61 : // traverse the JSON tree 62 1 : auto * current_node = &_root[value_keys[0]]; 63 2 : for (const auto key_index : index_range(value_keys)) 64 : { 65 2 : if (key_index == value_keys.size() - 1) 66 : { 67 1 : value = current_node->get<T>(); 68 1 : break; 69 : } 70 1 : current_node = &(*current_node)[value_keys[key_index + 1]]; 71 : } 72 1 : } 73 : /// Getter for vector values 74 : /** 75 : * Get a vector that is directly indexed at the root of the JSON file/tree 76 : * @param vector_name the name of the desired vector 77 : * @param vector_to_fill reference to the vector that will be set with the vector in the JSON 78 : */ 79 : template <typename T> 80 2 : void getVector(const std::string & vector_name, std::vector<T> & vector_to_fill) const 81 : { 82 2 : if (!_root.contains(vector_name)) 83 1 : mooseError("Attempted to get '", 84 : vector_name, 85 : "' but the JSON file does not contain this key at the root level"); 86 1 : vector_to_fill.clear(); 87 4 : for (const auto & item : _root[vector_name]) 88 3 : vector_to_fill.push_back(item.get<T>()); 89 1 : } 90 : /** 91 : * Get a vector in the JSON file/tree using the keys in the 'vector_keys' vector one by one 92 : * to traverse the JSON tree down to the requested vector 93 : * @param vector_keys the keys in descending order to access the vector 94 : * @param vector_to_fill reference to the vector that will be set with the vector in the JSON 95 : */ 96 : template <typename T> 97 28 : void getVector(const std::vector<std::string> & vector_keys, 98 : std::vector<T> & vector_to_fill) const 99 : { 100 28 : if (!vector_keys.size()) 101 1 : mooseError("There should be at least one key to retrieve a value from the JSON"); 102 : 103 : // traverse the JSON tree 104 27 : auto * current_node = &_root[vector_keys[0]]; 105 81 : for (const auto key_index : index_range(vector_keys)) 106 : { 107 81 : if (key_index == vector_keys.size() - 1) 108 : { 109 27 : if (!current_node->is_array()) 110 0 : mooseError("Cannot retrieve a vector from JSON node", 111 : *current_node, 112 : "obtained with last key", 113 : vector_keys[key_index]); 114 27 : vector_to_fill.clear(); 115 108 : for (const auto & item : *current_node) 116 81 : vector_to_fill.push_back(item.get<T>()); 117 27 : return; 118 : } 119 54 : if (current_node->is_array()) 120 0 : mooseError("Cannot obtain nested JSON item with key", 121 : vector_keys[key_index + 1], 122 : "because the current item is an array:", 123 : *current_node); 124 54 : current_node = &(*current_node)[vector_keys[key_index + 1]]; 125 : } 126 : } 127 : 128 : private: 129 : /** 130 : * Read the JSON file and load it into _root 131 : * @param filename the name of the file 132 : */ 133 : void read(const FileName & filename); 134 : 135 : /// Database filename 136 : const FileName & _filename; 137 : /// JSON data 138 : nlohmann::json _root; 139 : };