Read/write JSON to/from TObject

Hi,
Without using nlohmann’s library, but TBufferJSON instead, but what is the ROOT recommended way to work with JSON into TObject?

Example test.json file : {"a": 1, "b": 2}.

This:

std::ifstream f("test.json"); 
std::string s;
std::ostringstream ss;
ss << f.rdbuf();
s = ss.str();
TObject* obj = TBufferJSON::ConvertFromJSON(s.c_str());

// modify some values in the object

TString s2 = TBufferJSON::ConvertToJSON(obj);
std::ofstream outfile("out.json");
outfile << s2.Data(); 
outfile.close();

outputs null. Where is the mistake?

Thank you!

PS: I have already read I/O operations on JSON file - ROOT - ROOT Forum and Read JSON file in CERN ROOT - ROOT - ROOT Forum

@linev replied to the post you mentioned. May be he can help you ?

Hi,

You cannot convert arbitrary JSON into TObject.
ROOT requires to follow exact format that user-created JSON can be converted into C++ object.

Most easy way to understand ROOT JSON format - see how existing classes converted into JSON. For instance, TMarker class:

root [1] auto m = new TMarker(0.5, 0.5, 3);
root [2] TBufferJSON::ToJSON(m)
(TString) "{
  "_typename" : "TMarker",
  "fUniqueID" : 0,
  "fBits" : 0,
  "fMarkerColor" : 1,
  "fMarkerStyle" : 3,
  "fMarkerSize" : 1,
  "fX" : 0.5,
  "fY" : 0.5
}

You can create your own class with custom members, arrays and vectors inside.
And create JSON which match to structure of your class.

If you want to read arbitrary JSON data, you probably can directly use nlomann/json.hpp library for that.

Regards,
Sergey

1 Like

Thanks @linev. (I incorrectly thought I could import any arbitrary JSON and it would get populated into a blank TObject, but this is wrong, my bad).

BTW when using nlohmann::json, I get this error on Windows with VS 2022 + root_v6.32.12:

In file included from libtest dictionary payload:5:
In file included from E:/projects/src\Instrument.h:4:
In file included from C:/Program Files/root_v6.32.12\include\nlohmann/json.hpp:2440:
In file included from C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.43.34808\include\cassert:9:
In file included from C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\assert.h:12:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt.h:205:12: error: redefinition of '_CrtEnableIf<true, _Ty>'
    struct _CrtEnableIf<true, _Ty>
           ^~~~~~~~~~~~~~~~~~~~~~~

and lots of

==========================================
=============== STACKTRACE ===============
==========================================


================ Thread 0 ================
  libCore!TWinNTSystem::DispatchSignals()
  ucrtbase!seh_filter_exe()
  test!??
  VCRUNTIME140!_C_specific_handler()
  ntdll!_chkstk()
  ntdll!RtlRaiseException()

I found a temporary fix by editing nlohmann json.hpp around line 2440 into:

// allow overriding assert
#if !defined(JSON_ASSERT)
    //#include <cassert> // assert
    //#define JSON_ASSERT(x) assert(x)
    #define JSON_ASSERT(x)
#endif

Is there another way than this temporary fix?

Thank you again!

Hi,

One possible reason for the problem - if you are using nlohmann/json.hpp version which does not match with used by ROOT. If you run ROOT script (without compilation), just try:

root [0] auto res = nlohmann::json::parse("{ \"abc\": 7}");
root [1] std::cout << res["abc"] << std::endl;
7

Regards,
Sergey

Thanks.

I use nlohmann/json.hpp that is shipped with root (not another version that I would have downloaded).

I just tried root.exe and then:

root [0] #include <nlohmann/json.hpp>

immediately gives

In file included from ROOT_prompt_0:1:
In file included from C:/Program Files/root_v6.32.12\include\nlohmann/json.hpp:2440:
In file included from C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.43.34808\include\cassert:9:
In file included from C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\assert.h:12:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt\corecrt.h:205:12: error: redefinition of '_CrtEnableIf<true, _Ty>'
    struct _CrtEnableIf<true, _Ty>
           ^~~~~~~~~~~~~~~~~~~~~~~

With my “hacked” version with //#include <cassert> commented off, those error messages aren’t present and this works:

auto res = nlohmann::json::parse("{ \"abc\": 7}");
std::cout << res["abc"] << std::endl;

But #include <nlohmann/json.hpp> is not required.
ROOT already has dictionary for nlohmann classes - one can try to use them as is.

On Windows, if I launch C:\Program Files\root_v6.32.12\bin\root.exe and do directly auto res = nlohmann::..., I get this error:

Hi,

On my platform (OpenSUSE Linux) I have nlohmann/json.hpp installed system-wide.
Therefore ROOT can find and use it immediately.

Windows is always special.
If you can use modified version of nlohmann/json.hpp - do it.
This is most simple solution for you.

Regards,
Sergey

Thanks. On Windows, @bellenot, do you think I should modify json.hpp by commenting off the #include <cassert>: if you have time to look, can you reproduce this problem too, when launching root.exe and doing:

root [0] #include <nlohmann/json.hpp>

? Do you have same errors than here: Read/write JSON to/from TObject - #4 by jb023 ?

All the best

I don’t see the problem:

root [1] #include <nlohmann/json.hpp>
root [2] auto res = nlohmann::json::parse("{ \"abc\": 7}");
root [3] std::cout << res["abc"] << std::endl;
7
root [4]

How did you install ROOT?

I simply installed with root_v6.32.12.win64.vc17.exe.
I use Windows 10, and this:

C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0

I found in another forum topic (or github issue IIRC), that the problem could come from a different SDK version?

I don’t think so, but I’ll check