|
You only need to uncomment BOOST_SPIRIT_THREADSAFE if the Spirit library is being used in more than one thread. If you have a multi-threaded app but are only reading JSON data in one thread then you do not need to uncomment the define. The JSON writing code doesn't use Spirit and is thread safe. You will need to mutex protect Json Spirit values and objects, just as you would a plain C++ struct.
Regards
John
|
|
|
|
|
Again, I would recommend updating this article to Spirit2, it has no thread safety issues, completely stack based, and a lot faster.
Actually, would you be abject to me posting an article about my JSON parser I made in Spirit2? I would need to clean it up a lot, I just made it so it works and fast...
|
|
|
|
|
I have only just started, now that I have finally got the previous release out, a port to Spirit2. The lack of thread safety issues is another good reason to use Spirit2 that I did not know about. It is a bit fustrating to start with trying to figure out the new way to do something.
Are you talking about posting a new CodeProject article or about posting it to the JSON Spirit message board? Either way I would have no objection. I hope you will not mind me being influenced by any code you might post. I would credit you if I borrow too much
Regards
John
|
|
|
|
|
I tried to stick to the standard as close as I could, so mine differs from yours slightly (pure utf-8, unordered_map for objects, etc...). Mine is faster, but I use a very low level interface for things, should I write an article or something I would also want to make a wrapper for easy-access, but still have the low level available as it can be very useful in cases. Hmm, maybe make a C interface for compatibility...
And sure, can take whatever code I give out, I pretty much release my code under the boost license, I believe in pure code freedom (absolute crap the GPL is...).
|
|
|
|
|
Thanks for the explanation.
-Mike
|
|
|
|
|
Hi,
I have a question about allowed version of boost.
I have tried to configure json_spirit with boost-1_36 and got the following error.
Unable to find the requested Boost libraries.
Boost version: 1.36
Boost include path: /usr/include
Detected version of Boost is too old. Requested version was 1.37 (or newer).
Call Stack (most recent call first):
json_spirit/CMakeLists.txt:6 (FIND_PACKAGE)
I found it is caused by json_spirit/CMakeLists.txt having 'FIND_PACKAGE(Boost 1.37 REQUIRED)'.
I think json_spirit can be used with boost 1.34.0 or later, so the version in CMakeLists.txt is wrong.
Is it correct?
|
|
|
|
|
Yes it should be 1.34.0, I will correct it.
Thanks
John
|
|
|
|
|
Thank you for confirming
|
|
|
|
|
Hello again,
The library's working great so far; I'm using it to parse some JSON config files for an application.
In order to provide better documentation of my config files, I decided to add perl-style comments:
#Single-line comments, beginning with a hash sign
To do this, I added "comment_" to the "value_" and "rule" declarations in json_spirit_reader.cpp. I then added the comment rule:
comment_ = ch_p('#') >> *lex_escape_ch_p ;
This compiles, and my initial tests with it work, but it means that my application logic must catch and discard all comments, which seems wasteful and error-prone. I've read through the Boost::Spirit documentation, and it seems that I should be able to just "ignore" comments, the same way whitespace is ignored. But my head is still spinning from the Spirit User's Guide, and I've no idea how to make this work.
I realize this is outside the scope of json_spirit (it's not in the json specs), but I was wondering if you had any advice about implementing comments on top of json_spirit. I feel like I'm only two or three lines away from getting this to work properly, and I'd really appreciate any input you might have.
Thanks,
-->Seth
|
|
|
|
|
There is a build in comment parser, e.g. comment_p("#") which will match a '#' to the end of the line, see http://www.boost.org/doc/libs/1_36_0/libs/spirit/classic/doc/confix.html[^]
You will have to check that '#' characters inside strings are not matched.
I wouldn't call myself an expert on Spirit, only a user. The best place to ask questions is on the Spirit mailing list. I have always found them helpful and friendly.
Regards
John
|
|
|
|
|
Ah, that's just what I needed. I only had to add this to the ignore tokens, changing:
space_p
...to:
space_p | comment_p('#')
Now it all works just dandy.
Regarding '#' inside strings, I'm leaving the issue aside for now (The hash symbol isn't allowed in my config files anyway). But I'll definitely ask on the Spirit mailing list if (read "when") this requires a solution in the future.
Again, thanks.
-->Seth
|
|
|
|
|
I work with Spirit development quite a bit. If you added the comment to the skipper parser and the string parsing is lexemed (which it is), then you have no worries.
|
|
|
|
|
I have a problem using your library with std::strings
containing utf-8 encoded text; the library escapes the
utf8 data, because it thinks it is non printable data.
Any way to get around this? (Besides using utf-16 in
std::wstrings) Maybe an option to disable the escaping
or setting the encoding?
|
|
|
|
|
I have never needed to use unicode so I am clearly no expert but I had envisaged people converting unicode strings/files to and from wstrings before using the library. As I say in the documentation "Note that there is no support for reading Unicode files and converting them to wstrings as this is not a task specific to JSON."
Clearly this is not possible if you need to read/write a stream of utf-8. I do not know what a good solution would be. Perhaps allowing the user to provide an "is_printable" function to the writer, or as you say by allowing the user to set the encoding but I don't know much about that.
I will have a think about the problem, and try a few things out. If you have any further thought on a solution I would be very happy to hear them. A code patch, with test cases, would be ideal.
Regards
John
|
|
|
|
|
Thinking about this a bit I think you do need wstrings for UTF-8 as UTF-8 uses one to four bytes per code point.
Regards
John
|
|
|
|
|
As long as you keep in mind that i>std::string.size() does not return the
number of bytes and not the number of display characters you can store utf8
encoded strings in a std::string.
I will try to make a patch in a few days. I think I will use the is_printable
approach you mentioned. The only problem is that when using multibyte encodings
such as utf8 you will need more than the current character. I can think of two
approaches:
1. using lookahead: when encountering a character that might be the beginning
of a multibyte utf8 character, scan forward to see if it is valid.
2. keep history of the encountered characters and throw an exception when
a multibyte character appears to be invalid.
Do you have any preferences? Because I don't feel like writing a patch that
won't be accepted
|
|
|
|
|
I would very much like the JSON Spirit library to avoid the intricacies of unicode encodings. The idea is for library to be presented with unicode text held in wchars ( strings or streams ). Is it possible for you to use boost::utf8_codecvt_facet or something similar to get from utf8 to wchars and vise versa?
http://www.boost.org/doc/libs/1_41_0/libs/serialization/doc/codecvt.html[^]
|
|
|
|
|
I am currently looking into using your library (thanks for providing it!), and thus are too concerned with the handling of UTF-8 encoded data.
It is fine that JSON_Spirit can handle wchars -- but generally speaking, using wchars for unicode can't be recommended unconditionally. It adds a lot of complexity (and maybe even code bloat) for a very questionable benefit. (Is wchar even capable to represent all characters of the newer unicode standard? I doubt that). Unless the goal is to do real word processing or similar, it is often the best solution just to pass-through utf-8 encoded data, without the application even being aware of handling anything beyond simple 8bit chars.
Reading/Writing JSON fits nicely with that approach; you don't need to add anything beyond a very basic awareness to your library: Within a string element in JSON, any 8bit char is allowed, with the exception of the chars '"' and '\' which end the string or start an escape sequence respectively.
There is no possibility that an utf-8 sequence collides with this requirement. These sequences are specifically crafted, such as to assure that the highest order bit is always set. Thus it's sufficient for your library just to pass them on unaltered.
JSON_Spirit, in the current version is already able to handle utf-8, using just the normal std::string. The only problem is that the generated JSON isn't well readable for humans, because of the created escape sequences. For my use case, this sort-of counterfeits the very reason why I'm looking into JSON as a compact but human readable and editable format to store serialised object structures. If the escaping of "non printable" chars could somehow be toggled off or controlled by the client, the problem would already be solved.
|
|
|
|
|
That's interesting, I hadn't realised that no change is required to handle the reading UTF-8. A flag to toggle the escaping of "non printable" chars wouldn't be a problem to add. Would something like the following be sufficient?
template< class String_type >
String_type add_esc_chars( const String_type& s )
{
typedef typename String_type::const_iterator Iter_type;
typedef typename String_type::value_type Char_type;
String_type result;
const Iter_type end( s.end() );
for( Iter_type i = s.begin(); i != end; ++i )
{
const Char_type c( *i );
if( add_esc_char( c, result ) ) continue;
#ifdef HANDLE_UTF8
result += c;
#else
const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
if( iswprint( unsigned_c ) )
{
result += c;
}
else
{
result += non_printable_to_string< String_type >( unsigned_c );
}
#endif
}
return result;
}
Regards
John
|
|
|
|
|
yes, this looks OK. The UTF-8 sequences are being passed through unaltered.
I take it that the function add_esc_char(c,result) will somehow manage to handle the normal escape sequences, like \\ \" \n \t etc. (This funktion would need to have some embedded state, or inspect the rightmost character(s) of result).
But basically that's another question not realted to UTF-8 handling.
Regards,
Hermann Vosseler
|
|
|
|
|
Hi,
I'm trying to convert a small json string to map,
but with no success .
This the code I wrote:
char* res = "{\"responseData\": {\"translatedText\":\"hola mundo\"}, \"responseDetails\": null, \"responseStatus\": 200}";
Value_type value;
String_type in_s( to_str( res ) );
read_or_throw( in_s, value );
if (value.type()==obj_type)
{
Object_type obj;
obj = value.get_obj();
map<String_type,Value_type> mp_obj;
for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i )
mp_obj[ i->name_ ] = i->value_; <big></big>
}
but I get compilation error:
error C2039: 'name_' : is not a member of 'std::pair<_Ty1,_Ty2>'
Do u know what can cause the problem ?
I've added this code in
"json_spirit::test_reader, run_tests()"
10x for any help
|
|
|
|
|
I don't know what the exact type of your Object_type is. If it is a json_spirit::Object then you should not get the error. If it is a json_spirit::mObject then it is already a map and i->first is the pair's name, i->second is the pair's value.
Regards
John
|
|
|
|
|
thanks your code!
how to parse the string of {"a":1,"c" ,"dog":{"dogId":3,"isHungry" },"e":5,"exp":48810,"farmlandStatus":[{"a":34,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":26,"l":15,"m":15,"n":{"10177679":1,"16513950":1,"19783570":1,"20194034":1,"2175835":1,"25779663" ,"328410816":1,"3663649":1,"3783771":1,"41503729" ,"41892699" ,"43477953" ,"4469715" ,"532102" ,"538815525":1,"649460555" ,"8374675":1},"o" ,"p":[],"q":1260201288,"r":1260489476},{"a":55,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":28,"l":16,"m":16,"n":{"125462791":1,"13331147":1,"16513950":1,"2175835" ,"25779663":1,"294887051":1,"328410816" ,"3663649" ,"3783771" ,"41403882" ,"41503729" ,"41892699":1,"43477953":1,"4469715" ,"63322968":1,"649460555" ,"75031690":1,"8374675" ,"943310677":1},"o" ,"p":[],"q":1260321306,"r":1260492177},{"a":31,"b":1,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k" ,"l" ,"m" ,"n":[],"o" ,"p":[],"q":1260407625,"r":1260598769},{"a":34,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":30,"l":17,"m":17,"n":{"10177679" ,"16513950":1,"19783570":1,"20194034" ,"2175835":1,"25779663" ,"328410816" ,"3663649":1,"3783771":1,"41503729":1,"41892699":1,"43477953":1,"4469715" ,"532102" ,"538815525":1,"63322968":1,"649460555":1,"8374675":1},"o" ,"p":[],"q":1260201287,"r":1260490120},{"a":55,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":26,"l":15,"m":15,"n":{"16513950":1,"25779663" ,"3663649":1,"41503729":1,"41892699":1,"43477953":1,"4469715":1},"o" ,"p":[],"q":1260321278,"r":1260485140},{"a":31,"b":1,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k" ,"l" ,"m" ,"n":[],"o" ,"p":[],"q":1260407626,"r":1260595185},{"a":34,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":31,"l":18,"m":18,"n":{"10177679" ,"16513950":1,"19783570":1,"20194034":1,"2175835" ,"25779663":1,"328410816":1,"3663649":1,"3783771" ,"41503729":1,"41892699":1,"43477953" ,"4469715" ,"532102" ,"538815525" ,"63322968":1,"649460555":1,"8374675":1},"o" ,"p":[],"q":1260201287,"r":1260490120},{"a":55,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":25,"l":14,"m":14,"n":{"125462791" ,"13331147":1,"16513950":1,"2175835":1,"25779663" ,"328410816" ,"3663649":1,"3783771":1,"41503729":1,"41892699":1,"43477953" ,"4469715":1,"63322968":1,"649460555":1,"8374675" ,"943310677":1},"o" ,"p":[],"q":1260321277,"r":1260491057},{"a":31,"b":1,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k" ,"l" ,"m" ,"n":[],"o" ,"p":[],"q":1260407626,"r":1260595186},{"a":34,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":32,"l":19,"m":19,"n":{"10177679":1,"16513950":1,"19783570":1,"20194034":1,"25779663":1,"3663649":1,"3783771":1,"41503729":1,"41892699":1,"532102" ,"538815525":1,"649460555":1,"8374675":1},"o" ,"p":[],"q":1260201286,"r":1260483680},{"a":55,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":25,"l":14,"m":14,"n":{"16513950":1,"2175835":1,"25779663":1,"328410816":1,"3663649":1,"3783771" ,"41503729":1,"41892699":1,"43477953":1,"4469715":1,"63322968":1,"649460555" ,"8374675":1},"o" ,"p":[],"q":1260321276,"r":1260490120},{"a":33,"b":1,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k" ,"l" ,"m" ,"n":[],"o" ,"p":[],"q":1260407629,"r":1260595187},{"a":56,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j":2,"k":26,"l":15,"m":15,"n":{"10177679":1,"16513950":1,"260548988":1,"28364441":1,"361486206":1,"3783771":1,"41892699":1,"532102" ,"538815525":1,"649460555":1,"8374675":1},"o" ,"p":[],"q":1260346320,"r":1260461583},{"a":106,"b":6,"c" ,"d" ,"e":1,"f" ,"g" ,"h":1,"i":100,"j" ,"k":28,"l":16,"m":19,"n":{"110933010":1,"260548988":1,"3663649":1,"39206992":1,"41892699" ,"43477953":1,"63322968" ,"649460555" ,"75031690" },"o" ,"p":[],"q":1260407621,"r":1260600939}],"items":{"1":{"itemId":1},"2":{"itemId":98},"3":{"itemId":215},"4":{"itemId":100},"8":{"itemId":80003},"9":{"itemId":90001}},"user":{"healthMode":{"serverTime":1260601148,"set" ,"valid" },"pf":1}}
best regard!
robustwell
|
|
|
|
|
I am not sure what you are asking but -O , i.e. a capital letter O preceded by a minus sign which creates a smiley, is not a valid JSON object so cannot be parsed.
John
|
|
|
|
|
Thanks very much for making this useful library available.
I've found that JSON Spirit can't correctly handle the double numbers.
I have in JSON file:
{
"ground water volume flow rate" : 1234567890.123456789,
}
I read this value with:
...
jsonObj.at("ground water volume flow rate").get_real();
...
The number that I get is: 1.23457e+09
It looks like JSON Spirit handle the double numbers as float numbers (cuts till 6 decimal digits).
Is it possibe to get numbers as double?
Thanks, Tatjana
|
|
|
|
|