Would you consider accepting the Object_impl I have added in the code below (or something similar)? I think it is a good compromise between complexity, functionality, and your goal to maintain Object order for printing.
The use case I had was I had a templatized method to which you pass either an Object or wObject. In the method I needed to declare variables to hold a key and a value. But I could not find any way to get that type information.
And the question is what to put in those blanks. ObjectType::value_type evaluates to Pair or wPair, but there is no way to then get the correct string type.
Hello, i'm using your library in a backend server application. I've made some tweaks to improve performance and i'd like to share them and know your opinion.
1) Value_Impl
Created an union whith the bool_, i_ and d_
union{
bool bool_;
boost::int64_t i_;
double d_;
};
this change improved performance more than i expected.
I used json_spirit for a demo where we were only generating JSON. Since it seems to be the only JSON API supporting wide characters it was pretty much the only choice.
Now we are looking to add reading of JSON messages and I ran into a problem here. In this application I want to be able to have a sequence of JSON objects concatenated together. I want to read each one, process it, then move on to the next one. I'm sure you're asking why don't I put them into a JSON Array. The problem there is that would require parsing the entire array of objects before I can process any of them.
In other JSON parsers (e.g. org.JSON parser for Java) you can read a JSON object from an input stream then read another and so on. The JSONTokener object even provides a convenient more() method to check to see if there are more objects in the stream.
json_spirit on the other hand always consumes its entire input. When you pass it a stream it reads the entire stream into a string and sends the string to the parser. The return value will only say it successfully parsed if all of the input was consumed.
I would like to suggest that:
- end_p be removed from the grammar as you should not have to read to the end of the input.
- It would be nice if the parser could consume all whitespace after the value. Perhaps replacing the end_p with *space_p would do it.
- You should add new read calls that take an iterator pair (reference to begin iterator and end iterator value).
- This iterator-based read call should return parse_info.hit not parse_info.full because it does not have to consume the entire input.
- The reader calls that take input stream should call the iterator-based read call passing in an instance of istream_iterator.
That would then allow you to read a value without consuming all input. The string call should probably still return parse_info.full since you have no way to read further values. If you need to read a sequence of values then you can use the iterator call.
I'm curious about the choice of a std::vector for an Object. Property lookups in constant time pretty much rules out JSON Spirit for me. Nice clean API though, I would like to use it and I'm sure it is very handy for many. Thanks for your contribution.
Version 2.05 notes, "Linux version added". I don't see anything in 2.06 specific to Linux. Did it get omitted from build 2.06? Anyone have a copy of 2.05 I could get?
I have been trying to build in both Fedora 8 and 9 and haven't had any luck. If someone has a make file or script I would appreciate it.
We are hoping to use this package in a multithreaded application. We also want to leave the source code as untouched as possible so that any future upgrades will be as easy as downloading new source files and rebuilding the library. So, the 2 challenges I see are 1) defining BOOST_SPIRIT_THREADSAFE. Since we are building with a Makefile I suppose we can put a define for this in there and leave the one in the code commented out? 2) Linking to boost.thread. We would like to also take case of this without modifying any source files. Is there any way to dynamically link to boost.thread (using a makefile or otherwise)?
I have studies the code and boost spirit
but I still do not understand the treatment of
names without quotes.
In the code the definition of string_ is
string_
= lexeme_d // this causes white space inside a string to be retained
[
confix_p
(
'"',
*lex_escape_ch_p,
'"'
)
]
;
but of course strings are not only escaped characters. I cannot find
any other definition of string_ , I am very, very perplexed.
I need a language that easily defines structure for people
who want to spend the minimum amount of time writing: biologists
who describe how genes or metabolites interact. I read many
discussions that made reference to XML and JSON. The only
disadvantage of JSON is that every string needs to be surrounded
by quotes. This disadvantage is not only my own opinion.
That is the reason why I am trying to understand the parser.
For demo.txt I removed quotes around words without blanks, the
parser JSON Spirit had no problem reading the demo.txt .
I've made an effort to read and understand the C++ program but
what I see is perplexing as described in the first paragraph.
I need a confirmation by the author of the code, if I leave out
most nearly all quotes aside from imbedded space (which in fact
I will not be using in strings), will the parser read correctly.
If that is the case, JSON would be ideal for my purposes.
However, when integrating it into my project, I noticed some areas for improvement (I might be wrong, but thought I'd make the suggestion anyway):
1. Value always copies the string it is created with. This is fine when reading in a JSON stream, but not so good when creating a Value object manually for writing, since the string being output could be large (e.g. contents of a file, as in my case). So, I propose making either of the following change, that preserve the current behaviour by default, but give the users control over whether input string is copied: a) bool cp_; String *str_; Value(const String &s, bool copy = true) : str_(copy ? new(s) : &s), cp_(copy) {} ~Value() { if (cp_) delete str_; }
b) Value(String &s) { std::swap(str_, s); } // caller has to be aware that creating with non-const object has consequences, possibly fatal
2. Object holding a vector of Pairs seems too lax - will it accept the same property being specified twice. A boost::ptr_map<String, Value_impl> might be closer to the intent of a JSON object, and an added advantage is that Object class can implement the accessor very easily, with the [] operator.
3. Definition of Value_impl is actually not legal, because it declares containers of undefined classes. Using boost::ptr_vector<Value_impl> and boost::ptr_map<String, Value_impl> for Object and Array respectively should fix this.
Please let me know whether you think these changes well motivated. I am probably going to make these next week, and am happy to share the code if required.
I need to include a JSON string into a new object. Instead
of parsing the string and adding the resulting object I
would prefer to just add the string to the new object. Could
you include this feature in a future release?
The following is a patch that adds above functionality, maybe
you can use this if you want:
Hello,
I use boost 1.35 and json_spirit 2.05
I used the compiled lib in my project, with worked fine until i tried to write a file with json_spirit::write
then I got fatal error LNK1262: link failed due to mismatched versions c2.dll and LINK.EXE
Now I imported your source code files into my project instead of the library file. Now it works fine.
It's ok for me, but I like to know what was my failure
ps in my classed I used the lib by
using namespace json_spirit;
and
#include "json_spirit.h"
JSON Spirit is dependend to Boost, which I have installed and included in the project.
When using JSON Spirit in an other project as a static libary, will i have to link against boost? - will the target system have to have boost installed?
I am porting json_spitit to FreeBSD. I`m using autotools for building.
I hope my changes will work on various Unix system.
But some tests fail.
How I send my changes to you?
I have a small issue with the library, the protocol I'm implementing is using JSon values, more precisely JSon string values in some cases. And it appears that this is not supported by the current library, at least a comment in json_spirit_reader.h says so. So for my use case I tweaked the library a bit so that it does also return simple json values in addition to the object/arrays.
I've locally changed the lib in order to support non object/array values too, not 100% sure this is the right fix, so just posting it here as proposal. As it looks like I cannot attach anything here, so I will paste the changed functions below (sorry working on Win32 and I did not see a simple patch generation utility, so I'm just pasting the changed functions).
Note that I did also add tests, and in those the error case test for
"[1 2]" fails for me. In my understanding, this is not a legal JSon array as the required comma is missing. Well, I did not fix this issue, just wanted to have it reported too.
Daniel
json_spirit_reader.cpp:167 (replacement of the add_to_current function)
void add_to_current( const Value_t& value )
{
if (!current_p_)
{
value_ = Value_t(value);
current_p_ = &value_;
}
else if( current_p_->type() == array_type )
{
current_p_->get_array().push_back( value );
}
else if( current_p_->type() == obj_type )
{
current_p_->get_obj().push_back( Pair_t( name_, value ) );
}
else
{
assert(false);
}
}
There seems to a problem in handling a number with 10 or more digits. Have you encountered this.
I happened to notice when time was represented as milliseconds elapsed since 1970.
in json_demo.cpp I replaced "Essex Street" with "äöüß Street" to see how german umlaute would be treated. When executing the program then demo.txt contains "\u//.$\u///&\u///,\u//-/ Street" and reading the file yields an assert fault.
That's not so good. While working around the "const char *" problem is easy I don't know what to do here...
Has anyone been able to get this to build with VC6. I'm assuming the use of templates is beyond what VC6 is capable of.
I'm getting:
json_demo.cpp
../json_spirit\json_spirit_value.h(40) : error C2535: '__thiscall json_spirit::Value_impl<String>::json_spirit::Value_impl<String>(const class std::vector<struct json_spirit::Pair_impl<String>,class std::allocator<struct json_spirit::Pair_impl<Strin
g> > > &)' : member function already defined or declared
../json_spirit\json_spirit_value.h(39) : see declaration of 'Value_impl<String>::Value_impl<String>'
../json_spirit\json_spirit_value.h(71) : see reference to classtemplate instantiation 'json_spirit::Value_impl<String>' being compiled
../json_spirit\json_spirit_value.h(118) : error C2244: 'Value_impl<String>::Value_impl<String>::Value_impl<String>' : unable to resolve function overload
../json_spirit\json_spirit_value.h(120) : error C2954: template definitions cannot nest
../json_spirit\json_spirit_value.h(139) : error C2995: 'Value_impl<String>::Value_impl<String>' : template function has already been defined
../json_spirit\json_spirit_value.h(39) : see declaration of 'Value_impl<String>::Value_impl<String>'
\Libs\boost_1_33_1\boost/mpl/bool.hpp(37) : fatal error C1506: unrecoverable block scoping error
Error executing cl.exe.
I found this library extremely useful, but found a problem when using it to send larger floating point values.
Although floating point values are implemented using doubles, they are only transferred using single precision, so the following code will not transfer the value unchanged:
The fix is to change line 60 in json_spirit_writer.cpp from: case real_type: os_ << value.get_real(); break; to: case real_type: os_ << showpoint << setprecision(16) << value.get_real(); break; and to include the <iomanip> header file in that file.
Also, when fixing this could you please remove the '#pragma once' tags from the header files? The tags should not be necessary anymore and cause warnings under GCC. Other than that the library compiles fine under most OSs, so it would be good if the header files can be used with the same flexibility as Boost without generating warnings.
All in all a great little library, and please keep it coming.
Hello,
I tried to parse a simple JSON-string using the method read.
The string is
string s1= "{ \"method\" : \"echo\" }";
The parsing worked well and I printed the values of the parse_info-structure.
hit=1, full=1, stop=
Then I tried to parse a string containing to objects:
string s2= "{ \"method\" : \"echo\" }{ \"method2\" : \"echo2\" }";
The string gets parsed till the end of the first object. I
can write out the resulting value, but when viewing the info-
structure I get:
hit=0, full=0, stop="{ \"method2\" : \"echo2\" }";
I've looked up the API-documentation of boost spirit:
// hit: true if parsing is successful. This may be full:
// the parser consumed all the input, or partial:
// the parser consumed only a portion of the input.
Shoud hit not be 1? Have I missed something or is there an problem in json_spirit or boost spirit?
Kind Regards,
Augustinus Topor