Converted `JSON::String` to bool and numbers.

Previsouly when converting a JSON to a protobuf message in stout, we
cannot handle the fields like below which are actually valid.
  "int32": "-2147483647"
  "int64": "-9223372036854775807"
  "float": "1.5"
  "bool": "true"
The conversion will fail with an error like "Not expecting a JSON string
for field 'int32'".

So in this patch, `Try<Nothing> operator()(const JSON::String& string)`
was enhanced to be able to convert `JSON::String` to bool and numbers.
This is to match Google's json -> protobuf behavior, see the doc below
for details:
https://developers.google.com/protocol-buffers/docs/proto3#json

Review: https://reviews.apache.org/r/66025


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/499afcc0
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/499afcc0
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/499afcc0

Branch: refs/heads/master
Commit: 499afcc00c0510bfa42d641358604c7bf59e3e13
Parents: fcc6dee
Author: Qian Zhang <zhq527...@gmail.com>
Authored: Sun Mar 11 21:11:24 2018 +0800
Committer: Qian Zhang <zhq527...@gmail.com>
Committed: Wed Mar 14 08:18:53 2018 +0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/protobuf.hpp | 32 +++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/499afcc0/3rdparty/stout/include/stout/protobuf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/protobuf.hpp 
b/3rdparty/stout/include/stout/protobuf.hpp
index 4a1605e..69a54c9 100644
--- a/3rdparty/stout/include/stout/protobuf.hpp
+++ b/3rdparty/stout/include/stout/protobuf.hpp
@@ -412,7 +412,6 @@ struct Parser : boost::static_visitor<Try<Nothing>>
         break;
       case google::protobuf::FieldDescriptor::TYPE_BYTES: {
         Try<std::string> decode = base64::decode(string.value);
-
         if (decode.isError()) {
           return Error("Failed to base64 decode bytes field"
                        " '" + field->name() + "': " + decode.error());
@@ -452,6 +451,37 @@ struct Parser : boost::static_visitor<Try<Nothing>>
         }
         break;
       }
+      case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
+      case google::protobuf::FieldDescriptor::TYPE_FLOAT:
+      case google::protobuf::FieldDescriptor::TYPE_INT64:
+      case google::protobuf::FieldDescriptor::TYPE_SINT64:
+      case google::protobuf::FieldDescriptor::TYPE_SFIXED64:
+      case google::protobuf::FieldDescriptor::TYPE_UINT64:
+      case google::protobuf::FieldDescriptor::TYPE_FIXED64:
+      case google::protobuf::FieldDescriptor::TYPE_INT32:
+      case google::protobuf::FieldDescriptor::TYPE_SINT32:
+      case google::protobuf::FieldDescriptor::TYPE_SFIXED32:
+      case google::protobuf::FieldDescriptor::TYPE_UINT32:
+      case google::protobuf::FieldDescriptor::TYPE_FIXED32: {
+        Try<JSON::Number> number = JSON::parse<JSON::Number>(string.value);
+        if (number.isError()) {
+          return Error(
+              "Failed to parse '" + string.value + "' as a JSON number "
+              "for field '" + field->name() + "': " + number.error());
+        }
+
+        return operator()(number.get());
+      }
+      case google::protobuf::FieldDescriptor::TYPE_BOOL: {
+        Try<JSON::Boolean> boolean = JSON::parse<JSON::Boolean>(string.value);
+        if (boolean.isError()) {
+          return Error(
+              "Failed to parse '" + string.value + "' as a JSON boolean "
+              "for field '" + field->name() + "': " + boolean.error());
+        }
+
+        return operator()(boolean.get());
+      }
       default:
         return Error("Not expecting a JSON string for field '" +
                      field->name() + "'");

Reply via email to