Skip to content

Commit cdae258

Browse files
authored
[microsoft#1349] Expose json::value::parse for UTF8 string on Windows (microsoft#1350)
1 parent cb7ca74 commit cdae258

File tree

3 files changed

+69
-74
lines changed

3 files changed

+69
-74
lines changed

Release/include/cpprest/json.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,17 +390,37 @@ class value
390390
/// <summary>
391391
/// Parses a string and construct a JSON value.
392392
/// </summary>
393-
/// <param name="value">The C++ value to create a JSON value from, a C++ STL double-byte string</param>
393+
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string of the
394+
/// platform-native character width</param>
394395
_ASYNCRTIMP static value __cdecl parse(const utility::string_t& value);
395396

396397
/// <summary>
397398
/// Attempts to parse a string and construct a JSON value.
398399
/// </summary>
399-
/// <param name="value">The C++ value to create a JSON value from, a C++ STL double-byte string</param>
400+
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string of the
401+
/// platform-native character width</param>
400402
/// <param name="errorCode">If parsing fails, the error code is greater than 0</param>
401403
/// <returns>The parsed object. Returns web::json::value::null if failed</returns>
402404
_ASYNCRTIMP static value __cdecl parse(const utility::string_t& value, std::error_code& errorCode);
403405

406+
#ifdef _WIN32
407+
/// <summary>
408+
/// Parses a string and construct a JSON value.
409+
/// </summary>
410+
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string in
411+
/// UTF8 format</param>
412+
_ASYNCRTIMP static value __cdecl parse(const std::string& value);
413+
414+
/// <summary>
415+
/// Attempts to parse a string and construct a JSON value.
416+
/// </summary>
417+
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string in
418+
/// UTF8 format</param>
419+
/// <param name="errorCode">If parsing fails, the error code is greater than 0</param>
420+
/// <returns>The parsed object. Returns web::json::value::null if failed</returns>
421+
_ASYNCRTIMP static value __cdecl parse(const std::string& value, std::error_code& errorCode);
422+
#endif
423+
404424
/// <summary>
405425
/// Serializes the current JSON value to a C++ string.
406426
/// </summary>

Release/src/json/json_parsing.cpp

Lines changed: 31 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,10 +1120,11 @@ std::unique_ptr<web::json::details::_Value> JSON_Parser<CharType>::_ParseValue(
11201120
} // namespace json
11211121
} // namespace web
11221122

1123-
static web::json::value _parse_stream(utility::istream_t& stream)
1123+
template<typename CharType>
1124+
static web::json::value _parse_stream(std::basic_istream<CharType>& stream)
11241125
{
1125-
web::json::details::JSON_StreamParser<utility::char_t> parser(stream);
1126-
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
1126+
web::json::details::JSON_StreamParser<CharType> parser(stream);
1127+
typename web::json::details::JSON_Parser<CharType>::Token tkn;
11271128

11281129
parser.GetNextToken(tkn);
11291130
if (tkn.m_error)
@@ -1136,18 +1137,19 @@ static web::json::value _parse_stream(utility::istream_t& stream)
11361137
{
11371138
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
11381139
}
1139-
else if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
1140+
else if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
11401141
{
11411142
web::json::details::CreateException(tkn,
11421143
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
11431144
}
11441145
return value;
11451146
}
11461147

1147-
static web::json::value _parse_stream(utility::istream_t& stream, std::error_code& error)
1148+
template<typename CharType>
1149+
static web::json::value _parse_stream(std::basic_istream<CharType>& stream, std::error_code& error)
11481150
{
1149-
web::json::details::JSON_StreamParser<utility::char_t> parser(stream);
1150-
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
1151+
web::json::details::JSON_StreamParser<CharType> parser(stream);
1152+
typename web::json::details::JSON_Parser<CharType>::Token tkn;
11511153

11521154
parser.GetNextToken(tkn);
11531155
if (tkn.m_error)
@@ -1157,7 +1159,7 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod
11571159
}
11581160

11591161
auto returnObject = parser.ParseValue(tkn);
1160-
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
1162+
if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
11611163
{
11621164
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
11631165
}
@@ -1166,11 +1168,11 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod
11661168
return returnObject;
11671169
}
11681170

1169-
#ifdef _WIN32
1170-
static web::json::value _parse_narrow_stream(std::istream& stream)
1171+
template<typename CharType>
1172+
static web::json::value _parse_string(const std::basic_string<CharType>& str)
11711173
{
1172-
web::json::details::JSON_StreamParser<char> parser(stream);
1173-
web::json::details::JSON_StreamParser<char>::Token tkn;
1174+
web::json::details::JSON_StringParser<CharType> parser(str);
1175+
typename web::json::details::JSON_Parser<CharType>::Token tkn;
11741176

11751177
parser.GetNextToken(tkn);
11761178
if (tkn.m_error)
@@ -1183,18 +1185,19 @@ static web::json::value _parse_narrow_stream(std::istream& stream)
11831185
{
11841186
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
11851187
}
1186-
else if (tkn.kind != web::json::details::JSON_Parser<char>::Token::TKN_EOF)
1188+
else if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
11871189
{
11881190
web::json::details::CreateException(tkn,
11891191
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
11901192
}
11911193
return value;
11921194
}
11931195

1194-
static web::json::value _parse_narrow_stream(std::istream& stream, std::error_code& error)
1196+
template<typename CharType>
1197+
static web::json::value _parse_string(const std::basic_string<CharType>& str, std::error_code& error)
11951198
{
1196-
web::json::details::JSON_StreamParser<char> parser(stream);
1197-
web::json::details::JSON_StreamParser<char>::Token tkn;
1199+
web::json::details::JSON_StringParser<CharType> parser(str);
1200+
typename web::json::details::JSON_Parser<CharType>::Token tkn;
11981201

11991202
parser.GetNextToken(tkn);
12001203
if (tkn.m_error)
@@ -1204,7 +1207,7 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co
12041207
}
12051208

12061209
auto returnObject = parser.ParseValue(tkn);
1207-
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
1210+
if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
12081211
{
12091212
returnObject = web::json::value();
12101213
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
@@ -1213,53 +1216,12 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co
12131216
error = std::move(tkn.m_error);
12141217
return returnObject;
12151218
}
1216-
#endif
12171219

1218-
web::json::value web::json::value::parse(const utility::string_t& str)
1219-
{
1220-
web::json::details::JSON_StringParser<utility::char_t> parser(str);
1221-
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
1222-
1223-
parser.GetNextToken(tkn);
1224-
if (tkn.m_error)
1225-
{
1226-
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
1227-
}
1228-
1229-
auto value = parser.ParseValue(tkn);
1230-
if (tkn.m_error)
1231-
{
1232-
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
1233-
}
1234-
else if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
1235-
{
1236-
web::json::details::CreateException(tkn,
1237-
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
1238-
}
1239-
return value;
1240-
}
1220+
web::json::value web::json::value::parse(const utility::string_t& str) { return _parse_string(str); }
12411221

12421222
web::json::value web::json::value::parse(const utility::string_t& str, std::error_code& error)
12431223
{
1244-
web::json::details::JSON_StringParser<utility::char_t> parser(str);
1245-
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
1246-
1247-
parser.GetNextToken(tkn);
1248-
if (tkn.m_error)
1249-
{
1250-
error = std::move(tkn.m_error);
1251-
return web::json::value();
1252-
}
1253-
1254-
auto returnObject = parser.ParseValue(tkn);
1255-
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
1256-
{
1257-
returnObject = web::json::value();
1258-
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
1259-
}
1260-
1261-
error = std::move(tkn.m_error);
1262-
return returnObject;
1224+
return _parse_string(str, error);
12631225
}
12641226

12651227
web::json::value web::json::value::parse(utility::istream_t& stream) { return _parse_stream(stream); }
@@ -1270,10 +1232,17 @@ web::json::value web::json::value::parse(utility::istream_t& stream, std::error_
12701232
}
12711233

12721234
#ifdef _WIN32
1273-
web::json::value web::json::value::parse(std::istream& stream) { return _parse_narrow_stream(stream); }
1235+
web::json::value web::json::value::parse(const std::string& str) { return _parse_string(str); }
1236+
1237+
web::json::value web::json::value::parse(const std::string& str, std::error_code& error)
1238+
{
1239+
return _parse_string(str, error);
1240+
}
1241+
1242+
web::json::value web::json::value::parse(std::istream& stream) { return _parse_stream(stream); }
12741243

12751244
web::json::value web::json::value::parse(std::istream& stream, std::error_code& error)
12761245
{
1277-
return _parse_narrow_stream(stream, error);
1246+
return _parse_stream(stream, error);
12781247
}
12791248
#endif

Release/tests/functional/json/parsing_tests.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ SUITE(parsing_tests)
347347
VERIFY_ARE_EQUAL(U("K"), str.as_string());
348348

349349
str = json::value::parse(U("\"\\u20AC\""));
350-
// Euro sign as a hexidecmial UTF-8
350+
// Euro sign as a hexadecimal UTF-8
351351
const auto euro = to_string_t("\xE2\x82\xAC");
352352
VERIFY_ARE_EQUAL(euro, str.as_string());
353353

@@ -631,47 +631,53 @@ SUITE(parsing_tests)
631631
TEST(byte_ptr_parsing_array)
632632
{
633633
char s[] = "[ \"test1\",true]";
634+
json::value v = json::value::parse(s);
634635
std::stringstream ss;
635636
ss << s;
636-
json::value v = json::value::parse(ss);
637-
auto s2 = v.serialize();
637+
json::value vv = json::value::parse(ss);
638+
VERIFY_ARE_EQUAL(v, vv);
638639

640+
auto s2 = v.serialize();
639641
VERIFY_ARE_EQUAL(s2, U("[\"test1\",true]"));
640642

641643
std::stringstream os;
642-
v.serialize(os);
644+
vv.serialize(os);
643645
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
644646
}
645647

646648
TEST(byte_ptr_parsing_object)
647649
{
648650
char s[] = "{\"test1\":true }";
651+
json::value v = json::value::parse(s);
649652
std::stringstream ss;
650653
ss << s;
651-
json::value v = json::value::parse(ss);
652-
auto s2 = v.serialize();
654+
json::value vv = json::value::parse(ss);
655+
VERIFY_ARE_EQUAL(v, vv);
653656

657+
auto s2 = v.serialize();
654658
VERIFY_ARE_EQUAL(s2, U("{\"test1\":true}"));
655659

656660
std::stringstream os;
657-
v.serialize(os);
661+
vv.serialize(os);
658662
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
659663
}
660664

661665
TEST(Japanese)
662666
{
663667
utility::string_t ws = U("\"こんにちは\"");
664668
std::string s = to_utf8string(ws);
669+
json::value v = json::value::parse(s);
665670

666671
std::stringstream ss;
667672
ss << s;
668-
json::value v = json::value::parse(ss);
669-
auto s2 = v.serialize();
673+
json::value vv = json::value::parse(ss);
674+
VERIFY_ARE_EQUAL(v, vv);
670675

676+
auto s2 = v.serialize();
671677
VERIFY_ARE_EQUAL(s2, ws);
672678

673679
std::stringstream os;
674-
v.serialize(os);
680+
vv.serialize(os);
675681
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
676682
}
677683

0 commit comments

Comments
 (0)