Home | News | Documentation | Download

Reading a JSON file into ROOT C++

Hi,
I am trying to read a JSON file with some configuration options from ROOT (C++). It seems the nlohmann code is already in ROOT but I could not figure out how to use it in my macros/code.

I also tried to go through TPython using the json module in python, but again, I could not figure out how to transport this information back to C++ world.

I know of the TBufferJSON class too, but, again, I could not figure out how to use it.

Any hint or example code would be highly appreciated. Thanks,

Isidro


Please read tips for efficient and successful posting and posting code

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided


Hello iglez,

As far as I know, TBufferJSON only works to serialize/deserialize C++ objects supported by ROOT. If you have JSON that does not comply to the expected format (configuration data, etc.), I think that you may be able to use something like jsoncpp.

Please search for json on this forum, as there are already posts from other people that can help in solving your particular issue. If you cannot find a solution, do not hesitate to reply back here.

Cheers,
J.

Hi Javier,

Thanks for your answer.

I had a look in the forum before I posted my message and I did not find a good answer.

The funny thing for me is that the nlohmann json code for C++ was included in ROOT at least in some releases (here). But I don’t know if it can be used (and, if so, how) any more.

I don’t understand either how to use the TBufferJSON class myself (even if that involves creating a TObject derived class mimicking the json contents). Of course, given that my idea is to have simple json (actually a dictionary in the python sense) I could write a class and a reader, but I expected someone had already coded a generic reader given JSON is quite common.

Also, I failed with using TPython. I tried the following example:

File myjson.json

{
    "key1": "value1", 
    "key2": "value2"
}

File myjson.py

print('Creating class myjson...')

import json

class myjson:

    def __init__( self ):
        print('in myjson.__init__')

    def load( self ):
        print('In myjson.load')
        with open('myjson.json') as f: 
            self._json=json.load(f)

    def getdata( self ):
        return self._json

    def printdata( self ):
        print(self._json)

    def getdata( self, key):
        return self._json[key]

Then I try in interactive mode (could not get it to work in a macro)

root [0]   TPython::LoadMacro( "myjson.py" );
Creating class myjson...
root [1]   myjson mj;
in myjson.__init__
root [2]   mj.load();
**ROOT_prompt_2:1:9: error: too few arguments to function call, single argument 'a0' was not specified**
**mj.load();**
**~~~~~~~ ^**
**input_line_16:15:2: note: 'load' declared here**
** TPyReturn load(const TPyArg& a0) {**
 **^**
root [3]   std::string v1 = (char*) mj.getdata( "key1" );
Error in <TRint::HandleTermInput()>: std::logic_error caught: basic_string::_M_construct null not valid
root [4]   std::cout << "Value for key1 is "  << v1 << std::endl;
Value for key1 is 

And those are all my ideas :pensive:.

Cheers,

Isidro

Hi Isidro,

TBufferJSON can only be used for C++ classes with dictionary.
And produced JSON code has special format, which not always can be mapped to arbitrary JSON file.
But for simple structures it also looks very simple. Here is simple example:

struct Example1 {
   std::string key1;
   std::string key2;
};

void json()
{
   Example1 ex1;
   ex1.key1 = "name1";
   ex1.key2 = "name2";

   TString str = TBufferJSON::ToJSON(&ex1);

   printf("JSON\n%s\n", str.Data());

   auto res = TBufferJSON::FromJSON<Example1>(str.Data());

   printf("Decode %s %s\n", res->key1.c_str(), res->key2.c_str());
}

JSON code for that structure have to be:

{
   "_typename" : "Example1",
    "key1": "name1", 
    "key2": "name2"
}

Internally ROOT uses nlohmann/json parser, but it will be made public only in next 6.24 release (current master branch). nlohmann/json parser can parse arbitrary JSON file, but I have my doubts if this highly templated C++ library can be used via PyROOT.
Probably, you can use json parser, available in python.

Regards,
Sergey

Hi Sergey,
Thanks for the more detailed answer! It may serve what I want.

Please note that I don’t want to read JSON (a flat one) through python (which is easy). I want to read it from ROOT/C++. I thought of the TPython trick as a (quite awful) hack.

Asking around, some colleagues pointed me to boost.json (http://vinniefalco.github.io/doc/json/) which seems like an alternative too.

Cheers,

Isidro

You can also use yaml-cpp. Most of the time yaml and json are interchangeable, we have successfuly used yamlcpp and yaml in python in our analysis and the 2 were interchangable. In practice we have written the parser in c++ and linkdef it for python creating appropriate shared libraries for the module. I suppose one can do the same for c++ code compiled against jsoncpp libraries.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.