If you try #including libjson_spirit_writer_template.h in a project outside the JSON Spirit tree on a Linux box, it fails because libjson_spirit_writer_options.h isn't installed in /usr/local/include. The fix is trivial. Add:
Hi John,
first thank you for a wonderful product, it was a pleasure to use it.
I have noticed a small problem in a writer part:
if json data contains something like
"name": "\u05DE\u05E9\u05EA\u05DE\u05E9 \u05E8\u05D0\u05E9\u05D5\u05DF"
the unicode string is correctly parsed with son_spirit::read( std::wistream& is, wmValue& value ).
From the other hand, writing the parsed data write or write_formatted either produces a broken json.
I think that adding the following default case to the switch in
json_spirit::add_esc_char( Char_type c, String_type& s ) fixes this behavior:
Then the test.new file contains
only {"abc":1,"name":" for the original code, but {"abc":1,"name":"\u05DE\u05E9\u05EA\u05DE\u05E9 \u05E8\u05D0\u05E9\u05D5\u05DF","something":false} for the modified code.
And, apparently, the condition should be if(c <= 0 || c >= 128) and not the one i initially provided.
I don't see the problem using your exammple code. I get the correct text in "test.new". What version of JSON Spirit are you using? The function non_printable_to_string in json_spirit_writer_template.h outputs "\uXXXX" if a character is not printable.
Hi John,
non_printable_to_string is called only when !iswprint( unsigned_c ).
iswprint "returns a nonzero value if c is a printable wide character" (MSDN quoted) - and, in fact, the escaped characters in my example are valid hebrew ones - and therefore on the systems with hebrew language pack installed (like my one) iswprint returns true...
Why is iswprint returning true for valid hebrew characters a problem? A JSON string can contain any valid unicode character, the RFC says "All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)". I don't claim much knowledge of unicode but I would have thought therefore that the following would be valid JSON?
Hi John,
the problem is that if the character 'א' is written to the output stream as-is (that happens when iswprint('א') returns true), the output stream contains the hexadecimal sequence D105 which will be incorrectly processed, for example, by the output stream created with wofstream output("c:\\Temp\\test.new") (the ASCII one).
The problem is not specific to Hebrew, it will also happen with Greek, Cyrillic and any other non-Latin1 character set.
Of course, if the output stream internally supports UTF-8, the problem will not occur.
But, since your code doesn't make any assumptions regarding the output stream, IMHO it would be appropriate to stay on the safe side and to escape any non-ASCII character.
Please don't misunderstand me - it is your product, and the decision is entirely up to you, the patch i suggested solved my particular problem and i can live with that.
Let me say it again: i think your code is great, it helped me a lot and i really appreciate your work.
That's fine, I am glad you found the code helpful, I've just being trying to clarify in my mind what the issue is.
I would imagine that whether non-ascii characters should be escaped or not depends on the use case. Perhaps this should be an additional option to the write functions.
John, I was rather perturbed that when writing a largish (~200 nodes) and deep object tree it was taking 2.5 seconds. I investigated and found that excessive implicit copy constructors were being invoked when descending through each object. The problem exists for both vector and map versions but was worse for map (mObject). The fixes are as follows and are partly due to an incorrect const qualified typedef and functions returning by value instead of const reference
In json_spirit_value.h in struct Config_map
typedef std::pair< String_type, Value_type > Pair_type; should be typedef std::pair< String_type const, Value_type > Pair_type;
Note the added const qualifier - to see why look up any std::map documentation. This was resulting in a compiler forced copy to honour the (lack of) const on the std::map key type
This fix should also be applied to the get_name and _get_value functions in Config_vector
The above was causing the following function in json_spirit_writer_template.h to copy a full JSON sub tree into both get_name and get_value and return yet another copy from get_value
void output( const Obj_member_type& member )
{
output( Config_type::get_name( member ) ); space();
os_ << ':'; space();
output( Config_type::get_value( member ) );
}
thank you and congratulations for this library. Thanks to it, I managed to export a huge bunch of datas from a legacy monolithic code to a pretty fine json file, in a few hours of work. Same for reading stuffs. jason_spirit made me win a lot a time, thank you once again.
Fabulous work done by you sir......
Sir what i want to do is to take the JSON OBJECT as argument that i get from one of my method of C# DLL an parse it and store it in a file.
Can you tell which projects do i have to use and is there any change do i have to make?
I encounter problem with read/write of real numbers.
e.g.
the original value is 2.2086570657060003, and in "write" it is truncated to 2.208657065706.
Since my program doesn't manipulate the nodes of numbers at all, I want to add to the parser the option to remember the string representation of double value.
Namely treat doubles as strings, and in this way avoid any real numbers issues.
Is there a simple way to do it ?
I've put a breakpoint in the constructor of double Value, and the stack is quite deep with all the spirit scanner/parser/rules/policies etc. so I don't know if it's possible at all, or where to start.
Any help is appreciated, or other idea to solve the problem.
10x.
I did some small investigation, and found out that my input file contains doubles in various lengths of figures (I have no control of this input file at all).
When I write it, I need to choose the length and this causes the problem.
E.g.
if I use "remove_trailing_zeros_"
then input of
2.2086570657060003
is printed as
2.208657065706
If I dont use "remove_trailing_zeros_"
then input of
2.529573049612
is printed as
2.5295730496119999
Any arbitrary choice of length will cause some problems.
So if I can keep the original string of the json node, this will solve the problem.
Do you have any idea how to solve this issue using "json spirit" ?
Thanks.