Skip to content

Commit e722431

Browse files
Change Json library (#18)
1 parent 2061314 commit e722431

File tree

13 files changed

+8131
-59
lines changed

13 files changed

+8131
-59
lines changed

src/signalrclient/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ set (SOURCES
2121
websocket_transport.cpp
2222
../../third_party_code/cpprestsdk/uri.cpp
2323
../../third_party_code/cpprestsdk/uri_builder.cpp
24+
../../third_party_code/jsoncpp/jsoncpp.cpp
2425
)
2526

2627
include_directories(
27-
../../third_party_code/cpprestsdk)
28+
../../third_party_code/cpprestsdk
29+
../../third_party_code/jsoncpp)
2830

2931
add_library (signalrclient SHARED ${SOURCES})
3032

src/signalrclient/handshake_protocol.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ namespace signalr
1717
{ "protocol", signalr::value(protocol->name()) },
1818
{ "version", signalr::value((double)protocol->version()) }
1919
};
20-
return utility::conversions::to_utf8string(createJson(signalr::value(std::move(map))).serialize()) + record_separator;
20+
21+
return Json::writeString(getJsonWriter(), createJson(signalr::value(std::move(map)))) + record_separator;
2122
}
2223

2324
std::tuple<std::string, signalr::value> parse_handshake(const std::string& response)
@@ -28,9 +29,17 @@ namespace signalr
2829
throw signalr_exception("incomplete message received");
2930
}
3031
auto message = response.substr(0, pos);
31-
auto result = web::json::value::parse(utility::conversions::to_string_t(message));
32+
33+
Json::Value root;
34+
auto reader = getJsonReader();
35+
std::string errors;
36+
37+
if (!reader->parse(message.c_str(), message.c_str() + message.size(), &root, &errors))
38+
{
39+
throw signalr_exception(errors);
40+
}
3241
auto remaining_data = response.substr(pos + 1);
33-
return std::forward_as_tuple(remaining_data, createValue(result));
42+
return std::forward_as_tuple(remaining_data, createValue(root));
3443
}
3544
}
3645
}

src/signalrclient/json_helpers.cpp

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,78 +3,105 @@
33

44
#include "stdafx.h"
55
#include "json_helpers.h"
6+
#include <cmath>
67

78
namespace signalr
89
{
9-
signalr::value createValue(const web::json::value& v)
10+
signalr::value createValue(const Json::Value& v)
1011
{
1112
switch (v.type())
1213
{
13-
case web::json::value::Boolean:
14-
return signalr::value(v.as_bool());
15-
case web::json::value::Number:
16-
return signalr::value(v.as_double());
17-
case web::json::value::String:
18-
return signalr::value(utility::conversions::to_utf8string(v.as_string()));
19-
case web::json::value::Array:
14+
case Json::ValueType::booleanValue:
15+
return signalr::value(v.asBool());
16+
case Json::ValueType::realValue:
17+
case Json::ValueType::intValue:
18+
case Json::ValueType::uintValue:
19+
return signalr::value(v.asDouble());
20+
case Json::ValueType::stringValue:
21+
return signalr::value(v.asString());
22+
case Json::ValueType::arrayValue:
2023
{
21-
auto& array = v.as_array();
2224
std::vector<signalr::value> vec;
23-
for (auto& val : array)
25+
for (auto& val : v)
2426
{
2527
vec.push_back(createValue(val));
2628
}
2729
return signalr::value(std::move(vec));
2830
}
29-
case web::json::value::Object:
31+
case Json::ValueType::objectValue:
3032
{
31-
auto& obj = v.as_object();
3233
std::map<std::string, signalr::value> map;
33-
for (auto& val : obj)
34+
for (const auto& val : v.getMemberNames())
3435
{
35-
map.insert({ utility::conversions::to_utf8string(val.first), createValue(val.second) });
36+
map.insert({ val, createValue(v[val]) });
3637
}
3738
return signalr::value(std::move(map));
3839
}
39-
case web::json::value::Null:
40+
case Json::ValueType::nullValue:
4041
default:
4142
return signalr::value();
4243
}
4344
}
4445

45-
web::json::value createJson(const signalr::value& v)
46+
Json::Value createJson(const signalr::value& v)
4647
{
4748
switch (v.type())
4849
{
4950
case signalr::value_type::boolean:
50-
return web::json::value(v.as_bool());
51+
return Json::Value(v.as_bool());
5152
case signalr::value_type::float64:
52-
return web::json::value(v.as_double());
53+
{
54+
auto value = v.as_double();
55+
double intPart;
56+
// Workaround for 1.0 being output as 1.0 instead of 1
57+
// because the server expects certain values to be 1 instead of 1.0 (like protocol version)
58+
if (std::modf(value, &intPart) == 0)
59+
{
60+
return Json::Value((int)intPart);
61+
}
62+
return Json::Value(v.as_double());
63+
}
5364
case signalr::value_type::string:
54-
return web::json::value(utility::conversions::to_string_t(v.as_string()));
65+
return Json::Value(v.as_string());
5566
case signalr::value_type::array:
5667
{
5768
const auto& array = v.as_array();
58-
auto vec = std::vector<web::json::value>();
69+
Json::Value vec(Json::ValueType::arrayValue);
5970
for (auto& val : array)
6071
{
61-
vec.push_back(createJson(val));
72+
vec.append(createJson(val));
6273
}
63-
return web::json::value::array(vec);
74+
return vec;
6475
}
6576
case signalr::value_type::map:
6677
{
6778
const auto& obj = v.as_map();
68-
auto o = web::json::value::object();
79+
Json::Value object(Json::ValueType::objectValue);
6980
for (auto& val : obj)
7081
{
71-
o[utility::conversions::to_string_t(val.first)] = createJson(val.second);
82+
object[val.first] = createJson(val.second);
7283
}
73-
return o;
84+
return object;
7485
}
7586
case signalr::value_type::null:
7687
default:
77-
return web::json::value::null();
88+
return Json::Value(Json::ValueType::nullValue);
7889
}
7990
}
91+
92+
Json::StreamWriterBuilder getJsonWriter()
93+
{
94+
auto writer = Json::StreamWriterBuilder();
95+
writer["commentStyle"] = "None";
96+
writer["indentation"] = "";
97+
return writer;
98+
}
99+
100+
std::unique_ptr<Json::CharReader> getJsonReader()
101+
{
102+
auto builder = Json::CharReaderBuilder();
103+
Json::CharReaderBuilder::strictMode(&builder.settings_);
104+
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
105+
return reader;
106+
}
80107
}

src/signalrclient/json_helpers.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
#pragma once
55

66
#include "signalrclient/signalr_value.h"
7-
#include <cpprest/json.h>
7+
#include <json/json.h>
8+
#include <memory>
89

910
namespace signalr
1011
{
1112
static constexpr char record_separator = '\x1e';
1213

13-
signalr::value createValue(const web::json::value& v);
14+
signalr::value createValue(const Json::Value& v);
1415

15-
web::json::value createJson(const signalr::value& v);
16+
Json::Value createJson(const signalr::value& v);
17+
18+
Json::StreamWriterBuilder getJsonWriter();
19+
std::unique_ptr<Json::CharReader> getJsonReader();
1620
}

src/signalrclient/json_hub_protocol.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
#include "message_type.h"
77
#include "json_helpers.h"
88
#include "signalrclient/signalr_exception.h"
9+
#include "json/json.h"
910

1011
namespace signalr
1112
{
1213
std::string signalr::json_hub_protocol::write_message(const signalr::value& hub_message) const
1314
{
14-
return utility::conversions::to_utf8string(createJson(hub_message).serialize()) + record_separator;
15+
return Json::writeString(getJsonWriter(), createJson(hub_message)) + record_separator;
1516
}
1617

1718
std::vector<signalr::value> json_hub_protocol::parse_messages(const std::string& message) const
@@ -34,8 +35,16 @@ namespace signalr
3435

3536
signalr::value json_hub_protocol::parse_message(const std::string& message) const
3637
{
37-
auto result = web::json::value::parse(utility::conversions::to_string_t(message));
38-
auto value = createValue(result);
38+
Json::Value root;
39+
auto reader = getJsonReader();
40+
std::string errors;
41+
42+
if (!reader->parse(message.c_str(), message.c_str() + message.size(), &root, &errors))
43+
{
44+
throw signalr_exception(errors);
45+
}
46+
47+
auto value = createValue(root);
3948

4049
if (!value.is_map())
4150
{

src/signalrclient/negotiate.cpp

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "negotiate.h"
66
#include "url_builder.h"
77
#include "signalrclient/signalr_exception.h"
8+
#include "json_helpers.h"
89

910
namespace signalr
1011
{
@@ -54,65 +55,72 @@ namespace signalr
5455

5556
try
5657
{
57-
auto negotiation_response_json = web::json::value::parse(utility::conversions::to_string_t(http_response.content));
58+
Json::Value negotiation_response_json;
59+
auto reader = getJsonReader();
60+
std::string errors;
61+
62+
if (!reader->parse(http_response.content.c_str(), http_response.content.c_str() + http_response.content.size(), &negotiation_response_json, &errors))
63+
{
64+
throw signalr_exception(errors);
65+
}
5866

5967
negotiation_response response;
6068

61-
if (negotiation_response_json.has_field(_XPLATSTR("error")))
69+
if (negotiation_response_json.isMember("error"))
6270
{
63-
response.error = utility::conversions::to_utf8string(negotiation_response_json[_XPLATSTR("error")].as_string());
71+
response.error = negotiation_response_json["error"].asString();
6472
callback(std::move(response), nullptr);
6573
return;
6674
}
6775

6876
int server_negotiate_version = 0;
69-
if (negotiation_response_json.has_field(_XPLATSTR("negotiateVersion")))
77+
if (negotiation_response_json.isMember("negotiateVersion"))
7078
{
71-
server_negotiate_version = negotiation_response_json[_XPLATSTR("negotiateVersion")].as_integer();
79+
server_negotiate_version = negotiation_response_json["negotiateVersion"].asInt();
7280
}
7381

74-
if (negotiation_response_json.has_field(_XPLATSTR("connectionId")))
82+
if (negotiation_response_json.isMember("connectionId"))
7583
{
76-
response.connectionId = utility::conversions::to_utf8string(negotiation_response_json[_XPLATSTR("connectionId")].as_string());
84+
response.connectionId = negotiation_response_json["connectionId"].asString();
7785
}
7886

79-
if (negotiation_response_json.has_field(_XPLATSTR("connectionToken")))
87+
if (negotiation_response_json.isMember("connectionToken"))
8088
{
81-
response.connectionToken = utility::conversions::to_utf8string(negotiation_response_json[_XPLATSTR("connectionToken")].as_string());
89+
response.connectionToken = negotiation_response_json["connectionToken"].asString();
8290
}
8391

8492
if (server_negotiate_version <= 0)
8593
{
8694
response.connectionToken = response.connectionId;
8795
}
8896

89-
if (negotiation_response_json.has_field(_XPLATSTR("availableTransports")))
97+
if (negotiation_response_json.isMember("availableTransports"))
9098
{
91-
for (auto transportData : negotiation_response_json[_XPLATSTR("availableTransports")].as_array())
99+
for (const auto& transportData : negotiation_response_json["availableTransports"])
92100
{
93101
available_transport transport;
94-
transport.transport = utility::conversions::to_utf8string(transportData[_XPLATSTR("transport")].as_string());
102+
transport.transport = transportData["transport"].asString();
95103

96-
for (auto format : transportData[_XPLATSTR("transferFormats")].as_array())
104+
for (const auto& format : transportData["transferFormats"])
97105
{
98-
transport.transfer_formats.push_back(utility::conversions::to_utf8string(format.as_string()));
106+
transport.transfer_formats.push_back(format.asString());
99107
}
100108

101109
response.availableTransports.push_back(transport);
102110
}
103111
}
104112

105-
if (negotiation_response_json.has_field(_XPLATSTR("url")))
113+
if (negotiation_response_json.isMember("url"))
106114
{
107-
response.url = utility::conversions::to_utf8string(negotiation_response_json[_XPLATSTR("url")].as_string());
115+
response.url = negotiation_response_json["url"].asString();
108116

109-
if (negotiation_response_json.has_field(_XPLATSTR("accessToken")))
117+
if (negotiation_response_json.isMember("accessToken"))
110118
{
111-
response.accessToken = utility::conversions::to_utf8string(negotiation_response_json[_XPLATSTR("accessToken")].as_string());
119+
response.accessToken = negotiation_response_json["accessToken"].asString();
112120
}
113121
}
114122

115-
if (negotiation_response_json.has_field(_XPLATSTR("ProtocolVersion")))
123+
if (negotiation_response_json.isMember("ProtocolVersion"))
116124
{
117125
callback({}, std::make_exception_ptr(
118126
signalr_exception("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.")));

test/signalrclienttests/connection_impl_tests.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,10 +554,7 @@ TEST(connection_impl_start, start_fails_if_negotiate_response_is_invalid)
554554
mre.get();
555555
ASSERT_TRUE(false); // exception not thrown
556556
}
557-
catch (const std::exception & e)
558-
{
559-
ASSERT_STREQ("* Line 1, Column 28 Syntax error: Malformed token", e.what());
560-
}
557+
catch (const std::runtime_error&) { }
561558
}
562559

563560
TEST(connection_impl_start, negotiate_follows_redirect)

0 commit comments

Comments
 (0)