JSON: Support escape special chars. (#1758) v4.0.182

pull/2701/head
xmedia-systems 3 years ago committed by winlin
parent 061d544195
commit 34b968aabf

@ -8,6 +8,7 @@ The changelog for SRS.
## SRS 4.0 Changelog
* v4.0, 2021-10-20, Merge [#1758](https://github.com/ossrs/srs/pull/1758): JSON: Support escape special chars. v4.0.182
* v4.0, 2021-10-19, Merge [#1754](https://github.com/ossrs/srs/pull/1754): RTMP: If port is explicity set to 0, use default 1935. v4.0.181
* v4.0, 2021-10-18, Merge [#2670](https://github.com/ossrs/srs/pull/2670): SRT: Solve mpegts demux assert bug. v4.0.180
* v4.0, 2021-10-16, Merge [#2665](https://github.com/ossrs/srs/pull/2665): API: Fix the same 'client_id' error when asynchronous call. v4.0.179

@ -9,6 +9,6 @@
#define VERSION_MAJOR 4
#define VERSION_MINOR 0
#define VERSION_REVISION 181
#define VERSION_REVISION 182
#endif

@ -1538,17 +1538,31 @@ SrsJsonArray* SrsJsonAny::to_array()
return p;
}
string escape(string v)
// @see https://github.com/ossrs/srs/pull/1758/files#diff-9568479ef5cb0aa1ade2381e11e9c066c01bf9c4bbed70ffa27094d08bb27380R370
// @see https://github.com/json-parser/json-builder/blob/2d8c6671926d104c5dcd43ccd2b1431a3f0299e0/json-builder.c#L495
string json_serialize_string(const string& v)
{
stringstream ss;
for (int i = 0; i < (int)v.length(); i++) {
if (v.at(i) == '"') {
ss << '\\';
ss << "\"";
const char* start = v.data();
const char* end = start + v.length();
for (const char* p = start; p < end; ++p) {
switch (*p) {
case '"': ss << '\\' << '"'; break;
case '\\': ss << '\\' << '\\'; break;
case '\b': ss << '\\' << 'b'; break;
case '\f': ss << '\\' << 'f'; break;
case '\n': ss << '\\' << 'n'; break;
case '\r': ss << '\\' << 'r'; break;
case '\t': ss << '\\' << 't'; break;
default: ss << *p;
}
ss << v.at(i);
}
ss << "\"";
return ss.str();
}
@ -1556,7 +1570,9 @@ string SrsJsonAny::dumps()
{
switch (marker) {
case SRS_JSON_String: {
return "\"" + escape(to_str()) + "\"";
SrsJsonString* p = dynamic_cast<SrsJsonString*>(this);
srs_assert(p != NULL);
return json_serialize_string(p->value);
}
case SRS_JSON_Boolean: {
return to_boolean()? "true" : "false";

@ -2626,6 +2626,72 @@ VOID TEST(ProtocolJSONTest, Dumps)
}
}
VOID TEST(ProtocolJSONTest, DumpsSpecialChars)
{
if (true) {
SrsJsonAny* p = SrsJsonAny::str("hello");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"hello\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\"llo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\\"llo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\\llo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\\\llo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\nllo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\nllo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\tllo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\tllo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\bllo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\bllo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\fllo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\fllo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("he\rllo");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"he\\rllo\"", p->dumps().c_str());
srs_freep(p);
}
if (true) {
SrsJsonAny* p = SrsJsonAny::str("hello视频");
EXPECT_TRUE(p->is_string());
EXPECT_STREQ("\"hello\xE8\xA7\x86\xE9\xA2\x91\"", p->dumps().c_str());
srs_freep(p);
}
}
VOID TEST(ProtocolJSONTest, Parse)
{
if (true) {

Loading…
Cancel
Save