Domanda

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?

È stato utile?

Soluzione

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];
        }
    }
}

Altri suggerimenti

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();                                                                                                  
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top