Question

I am using jsoncpp to read settings from a JSON file.

I would like to have two cascading settings file, say MasterSettings.json and LocalSettings.json where LocalSettings is a subset of MasterSettings. I would like to load MasterSettings first and then LocalSettings. Where LocalSettings has a value that differs from MasterSettings, that value would overwrite the one from MasterSettings. Much like the cascade in CSS.

Is there any elegant way to do this with jsoncpp?

Was it helpful?

Solution

I'm going to assume your settings files are JSON objects.

As seen here, when JSONCpp parses a file, it clears the contents of the root node. This mean that trying to parse a new file on top of the old one won't preserve the old data. However, if you parse both files into separate Json::Value nodes, it's straight forward to recursively copy the values yourself by iterating over the keys in the second object using getMemberNames.

// Recursively copy the values of b into a. Both a and b must be objects.
void update(Json::Value& a, Json::Value& b) {
    if (!a.isObject() || !b.isObject()) return;

    for (const auto& key : b.getMemberNames()) {
        if (a[key].isObject()) {
            update(a[key], b[key]);
        } else {
            a[key] = b[key];
        }
    }
}

OTHER TIPS

I know it has been a while. but...

In addition to the correct answer and the commentary, here is a code version for those who use a older g++ version:

void jsonMerge(Json::Value &a, Json::Value &b) {                                                                        
                                                                                                                  
   if (!a.isObject() || !b.isObject()) return;                                                                           
                                                                                                                    
   vector<string> member_name = b.getMemberNames();                                                                      
   string key = "";                                                                                                      
   for (unsigned i = 0, len = member_name.size(); i < len; i++) {                                                        
       key = member_name[i];                                                                                               
                                                                                                                    
       if (!a[key].isNull() && a[key].type() == Json::objectValue && b[key].type() == Json::objectValue) {                 
           jsonMerge(a[key], b[key]);                                                                                        
       } else {                                                                                                            
           a[key] = b[key];                                                                                                  
       }                                                                                                                   
   }                                                                                                                     
   member_name.clear();                                                                                                  
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top