Writing a blog post sometimes can be useful to get some face-palm kind of programming error out of one’s system.
Putting such an error into written words then serves a couple of purposes:
- it helps oneself remembering
- it helps others who read it not to do the same thing
- it serves as error log for future reference
So here it comes:
In one project we use JSON to serialize objects in order to send them over HTTP (we use the very nice JSON Spirit library, btw).
For each object we have serialize/deserialize methods which do the heavy lifting. After having developed a new deserialize method I wanted to test it together with the HTTP request handling. Using curl for this I issued a command like this:
curl -X PUT http://localhost:30222/some/url -d @datafile
This command issues a PUT request to the given URL and uses data in ./datafile, which contains the JSON, as request data.
The request came through but the deserializer wouldn’t do its work. WTF? Let’s see what goes on – let’s put some debug output in:
MyObject MyObjectSerializer::deserialize(std::istream& jsonIn) { // debug output starts here std::string stringToDeserialize; Poco::StreamCopier::copyToString(jsonIn, stringToDeserialize); std::cout << "The String: " << stringToDeserialize << std::endl; // debug output ends here json_spirit::Value value; json_spirit::read(jsonIn, value); ... }
I’ll give you some time to spot the bug…. 3..2..1..got it? Please check Poco::StreamCopier documentation if you are not familiar with POCO libraries.
What’s particularly misleading is the “Copier” part of the name StreamCopier, because it does not exactly copy the bytes from the stream into the string – it moves them. This means that after the debug output code, the istream is empty.
Unfortunately, I did not immediately recognize the change in the error outputs of the JSON parser. This might have given me a hint to the real problem. Instead, during the next half hour I searched for errors in the JSON I was sending.
When I finally realized it …