Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overriding default values? #1083

Closed
simulationcloud opened this issue May 10, 2018 · 8 comments
Closed

Overriding default values? #1083

simulationcloud opened this issue May 10, 2018 · 8 comments
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@simulationcloud
Copy link

I have a json file that I read in using nlohmann:json. It contains nested dicts/lists that are configurations specified by users.

Only when a user specifies a value in this file (read in to a json object) should it override the default value, which is specified by another json object.

My question is: what's the easiest way to replace all the items in one json object with that of another json object, if that item exists in the other json object?

@nlohmann
Copy link
Owner

There is the update function that could be used for this. You could load the default values in a value v and then call v.update(u) where u are the values given by the user.

@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label May 11, 2018
@simulationcloud
Copy link
Author

Hi nlohmann, thanks for the help. When I call update, I get this error:
terminate called after throwing an instance of 'nlohmann::detail::type_error'
what(): [json.exception.type_error.312] cannot use update() with array

My default object looks like:
json jsn =
{
"geometry" ,
{
"endianness" , "little"
},
"nsSolver" ,
{
"tol" , 1.0e-8,
"CFL0" , 1.0,
"CFL1" , 200.0,
"CFLsteps" , 100,
"JacobiSweeps" , 30
},
"ransSolver" ,
{
"tol" , 1.0e-6,
"JacobiSweeps" , 30
},
"freestream" ,
{
"Re" , 1000.0,
"M" , 0.5,
"Tref" , 300,
"alpha" , 0.0,
"beta" , 0.0
},
{
"boundaries",
{

        }
   }
};

It seems it may be complaining about the hierarchy?

@nlohmann
Copy link
Owner

It says that you can only call update on an object. Can you provide the code where you call update?

@simulationcloud
Copy link
Author

simulationcloud commented May 14, 2018

Here's the whole code:

#include "ParseInput.h"
#include "nlohmann/json.hpp"
#include <fstream>
#include <iostream>

json getDefaultConfig(void){
    json jsn =
    {
        "geometry" ,
        {
            "endianness" , "little"
        },
        "nsSolver" ,
        {
            "tol" , 1.0e-8,
            "CFL0" , 1.0,
            "CFL1" , 200.0,
            "CFLsteps" , 100,
            "JacobiSweeps" , 30
        },
        "ransSolver" ,
        {
            "tol" , 1.0e-6,
            "JacobiSweeps" , 30
        },
        "freestream" ,
        {
            "Re" , 1000.0,
            "M" , 0.5,
            "Tref" , 300,
            "alpha" , 0.0,
            "beta" , 0.0
        },
        {
            "boundaries",
            {

            }
       }
    };
    return jsn;
}

json readConfig(std::string file){
    std::ifstream i(file);
    json j;
    i >> j;
    i.close();

    json dflt = getDefaultConfig();
    //dflt.update(j.begin(), j.end());
    for(auto it= j.begin(); it != j.end(); ++it){
        dflt[it.key()].update(it.value());
    }
    return dflt;
}

@nlohmann
Copy link
Owner

What would be the content of an input file?

@simulationcloud
Copy link
Author

simulationcloud commented May 15, 2018

The example content of an input file is:

{
    "geometry" :
    {
        "meshName" : "wing.ugrid",
        "endianness" : "little"
    },
    "nsSolver" :
    {
        "tol" : 1.0e-8,
        "CFL0" : 0.1,
        "CFL1" : 500.0,
        "CFLsteps" : 100,
        "JacobiSweeps" : 50
    },
    "ransSolver" :
    {
        "tol" : 1.0e-6,
        "CFL0" : 0.1,
        "CFL1" : 5.0,
        "CFLsteps" : 100,
        "JacobiSweeps" : 50
    },
    "freestream" :
    {
        "Re" : 10000.0,
        "M" : 0.25,
        "Tref" : 300,
        "alpha" : 0.0,
        "beta" : 0.0
    },
    "boundaries" : {
        "1" : {
            "type" : "NoSlipWall"
        },
        "2" : {
            "type" : "SlipWall"
        },
        "3" : {
            "type" : "Freestream"
        }
    }
}

Thanks for the help!

@nlohmann
Copy link
Owner

I think the issue is the JSON value returned by getDefaultConfig. I think you want to create an object, but you actually create this:

[
    "geometry",
    [
        "endianness",
        "little"
    ],
    "nsSolver",
    [
        "tol",
        "1e-08",
        "CFL0",
        1.0,
        "CFL1",
        200.0,
        "CFLsteps",
        100,
        "JacobiSweeps",
        30
    ],
    "ransSolver",
    [
        "tol",
        "1e-06",
        "JacobiSweeps",
        30
    ],
    "freestream",
    [
        "Re",
        1000.0,
        "M",
        0.5,
        "Tref",
        300,
        "alpha",
        0.0,
        "beta",
        0.0
    ],
    [
        "boundaries",
        {}
    ]
]

You need to take care about the braces required to create an object:

json j = { {"key", "value"} };

That is, you need to have an extra pair of braces around each key/value pair.

@nlohmann
Copy link
Owner

I assumed how your JSON value should look like.

#include <iostream>
#include <fstream>
#include "json.hpp"

using json = nlohmann::json;

json getDefaultConfig(void){
    json jsn = R"(
    {
        "geometry": {
            "endianness": "little"
        },
        "nsSolver": {
            "tol": 1e-08,
            "CFL0": 1.0,
            "CFL1": 200.0,
            "CFLsteps": 100,
            "JacobiSweeps": 30
        },
        "ransSolver": {
            "tol": 1e-06,
            "JacobiSweeps": 30
        },
        "freestream": {
            "Re": 1000.0,
            "M": 0.5,
            "Tref": 300,
            "alpha": 0.0,
            "beta": 0.0
        },
        "boundaries": {}
    })"_json;
    return jsn;
}

json readConfig(std::string file){
    std::ifstream i(file);
    json j;
    i >> j;
    i.close();
    
    json dflt = getDefaultConfig();
    
    //dflt.update(j.begin(), j.end());
    for(auto it= j.begin(); it != j.end(); ++it) {
        dflt[it.key()].update(it.value());
    }
    return dflt;
}

int main() {
    auto j = readConfig("file.json");
    std::cout << std::setw(2) << j << std::endl;
}

Output:

{
  "boundaries": {
    "1": {
      "type": "NoSlipWall"
    },
    "2": {
      "type": "SlipWall"
    },
    "3": {
      "type": "Freestream"
    }
  },
  "freestream": {
    "M": 0.25,
    "Re": 10000.0,
    "Tref": 300,
    "alpha": 0.0,
    "beta": 0.0
  },
  "geometry": {
    "endianness": "little",
    "meshName": "wing.ugrid"
  },
  "nsSolver": {
    "CFL0": 0.1,
    "CFL1": 500.0,
    "CFLsteps": 100,
    "JacobiSweeps": 50,
    "tol": 1e-08
  },
  "ransSolver": {
    "CFL0": 0.1,
    "CFL1": 5.0,
    "CFLsteps": 100,
    "JacobiSweeps": 50,
    "tol": 1e-06
  }
}

@nlohmann nlohmann closed this as completed Jun 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants