-
Notifications
You must be signed in to change notification settings - Fork 11
Conversation
igorpeshansky
commented
Dec 19, 2017
- Throw an exception on parse errors.
- Allow parsing JSON streams with multiple objects.
- Factor out streaming operators for request/response headers.
- Remove superfluous std::bind calls.
@supriyagarg, you might want to review as well. |
src/json.cc
Outdated
if (all_values.size() > 1) { | ||
std::ostringstream out; | ||
out << "Getting a single value out of " << all_values.size(); | ||
throw json::Exception(out.str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this really be an exception instead a warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I want this to be an error. This really means an expectation mismatch, and I don't want to drop the other values with just a bit of log spam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we only had the option to fetch a single value and that would either return the value or return a nullptr
. The contract has changed since then, is there any code that would be negatively impacted by this? If so, have those already been surrounded by the appropriate try
/ catch
blocks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep the two separate. Previously, we only queried endpoints that would return a single JSON object at a time, so this should be fully backward compatible. We also used to return nullptr
in case of a parse error, and now we throw an exception, but all those uses have been updated as part of this PR.
To answer @qingling128's comment, the old API always parsed a single value. The new implementation parses a vector of values. However, when only a single value is requested, we want to validate the input by ensuring that the parsed vector is a singleton. I've updated the error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused reading this part as well. So we take a vector and want to make sure it has exactly one element? If so, shouldn't the exception message Getting a single value out of
be changed to Getting more than one value out of
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for changing the error message. LGTM now.
static std::unique_ptr<Value> FromStream(std::istream& stream); | ||
static std::unique_ptr<Value> FromString(const std::string& input); | ||
static std::vector<std::unique_ptr<Value>> AllFromStream( | ||
std::istream& stream) throw(Exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we limit the throw to a json::Exception
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is json::Exception
. This code is within the json
namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I was confused, why is it that we need to include json::
here despite also being in the json
namespace?
Line 250 in 1edb94f
throw json::Exception("There is no " + field + " in " + ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a typo. Fixed (there and in json.cc
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Responded. PTAL.
src/json.cc
Outdated
if (all_values.size() > 1) { | ||
std::ostringstream out; | ||
out << "Getting a single value out of " << all_values.size(); | ||
throw json::Exception(out.str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I want this to be an error. This really means an expectation mismatch, and I don't want to drop the other values with just a bit of log spam.
static std::unique_ptr<Value> FromStream(std::istream& stream); | ||
static std::unique_ptr<Value> FromString(const std::string& input); | ||
static std::vector<std::unique_ptr<Value>> AllFromStream( | ||
std::istream& stream) throw(Exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is json::Exception
. This code is within the json
namespace.
JSONBuilder builder; | ||
|
||
const int kMax = 65536; | ||
unsigned char data[kMax]; | ||
yajl_handle handle = yajl_alloc(&callbacks, NULL, (void*) &builder); | ||
yajl_config(handle, yajl_allow_comments, 1); | ||
yajl_config(handle, yajl_allow_multiple_values, 1); | ||
//yajl_config(handle, yajl_allow_trailing_garbage, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we commenting out these two lines on purpose? If so, maybe leave a comment for the reason and under what circumstances we might want to uncomment them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. These were robustness changes that would allow us to talk to less formalized APIs. I decided we should instead do some validation on the Kubernetes API, but if it turns out to be buggy or unstable, we may end up uncommenting these.
I thought that the option names (allow_trailing_garbage
and dont_validate_strings
) were self-descriptive enough that they didn't merit a separate comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Now I understand.
src/json.cc
Outdated
if (all_values.size() > 1) { | ||
std::ostringstream out; | ||
out << "Getting a single value out of " << all_values.size(); | ||
throw json::Exception(out.str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused reading this part as well. So we take a vector and want to make sure it has exactly one element? If so, shouldn't the exception message Getting a single value out of
be changed to Getting more than one value out of
instead?
|
||
namespace google { | ||
|
||
// Allow logging request headers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "allow" mean in this context? The method seems straight forward though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means "enable" -- without this method, using log << req.headers()
would fail to compile. However, "enable" is overloaded (e.g., could mean a config option), so I went with a more neutral word.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Thanks for the clarification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed feedback. PTAL.
src/json.cc
Outdated
if (all_values.size() > 1) { | ||
std::ostringstream out; | ||
out << "Getting a single value out of " << all_values.size(); | ||
throw json::Exception(out.str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep the two separate. Previously, we only queried endpoints that would return a single JSON object at a time, so this should be fully backward compatible. We also used to return nullptr
in case of a parse error, and now we throw an exception, but all those uses have been updated as part of this PR.
To answer @qingling128's comment, the old API always parsed a single value. The new implementation parses a vector of values. However, when only a single value is requested, we want to validate the input by ensuring that the parsed vector is a singleton. I've updated the error message.
static std::unique_ptr<Value> FromStream(std::istream& stream); | ||
static std::unique_ptr<Value> FromString(const std::string& input); | ||
static std::vector<std::unique_ptr<Value>> AllFromStream( | ||
std::istream& stream) throw(Exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a typo. Fixed (there and in json.cc
).
|
||
namespace google { | ||
|
||
// Allow logging request headers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means "enable" -- without this method, using log << req.headers()
would fail to compile. However, "enable" is overloaded (e.g., could mean a config option), so I went with a more neutral word.
JSONBuilder builder; | ||
|
||
const int kMax = 65536; | ||
unsigned char data[kMax]; | ||
yajl_handle handle = yajl_alloc(&callbacks, NULL, (void*) &builder); | ||
yajl_config(handle, yajl_allow_comments, 1); | ||
yajl_config(handle, yajl_allow_multiple_values, 1); | ||
//yajl_config(handle, yajl_allow_trailing_garbage, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. These were robustness changes that would allow us to talk to less formalized APIs. I decided we should instead do some validation on the Kubernetes API, but if it turns out to be buggy or unstable, we may end up uncommenting these.
I thought that the option names (allow_trailing_garbage
and dont_validate_strings
) were self-descriptive enough that they didn't merit a separate comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
|
||
namespace google { | ||
|
||
// Allow logging request headers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Thanks for the clarification.
JSONBuilder builder; | ||
|
||
const int kMax = 65536; | ||
unsigned char data[kMax]; | ||
yajl_handle handle = yajl_alloc(&callbacks, NULL, (void*) &builder); | ||
yajl_config(handle, yajl_allow_comments, 1); | ||
yajl_config(handle, yajl_allow_multiple_values, 1); | ||
//yajl_config(handle, yajl_allow_trailing_garbage, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. Now I understand.
src/json.cc
Outdated
if (all_values.size() > 1) { | ||
std::ostringstream out; | ||
out << "Getting a single value out of " << all_values.size(); | ||
throw json::Exception(out.str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for changing the error message. LGTM now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
LGTM |