Skip to content

Commit 273a6e4

Browse files
Refactor JSON serialization and escape handling
#1682
1 parent bdbad0d commit 273a6e4

File tree

1 file changed

+32
-48
lines changed

1 file changed

+32
-48
lines changed

nanoFramework.Json/JsonConvert.cs

Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ private struct LexToken
3333
/// <summary>
3434
/// Convert an object to a JSON string.
3535
/// </summary>
36-
/// <param name="oSource">The value to convert. Supported types are: Boolean, String, Byte, (U)Int16, (U)Int32, Float, Double, Decimal, Array, IDictionary, IEnumerable, Guid, Datetime, DictionaryEntry, Object and null.</param>
36+
/// <param name="oSource">The value to convert. Supported types are: Boolean, String, Byte, (U)Int16, (U)Int32,
37+
/// Float, Double, Decimal, Array, IDictionary, IEnumerable, Guid, Datetime, DictionaryEntry, Object and null.
38+
/// </param>
3739
/// <returns>The JSON object as a string or null when the value type is not supported.</returns>
3840
/// <remarks>For objects, only public properties with getters are converted.</remarks>
3941
public static string SerializeObject(object oSource)
@@ -1088,7 +1090,7 @@ private static LexToken GetNextTokenInternal(ref int jsonPos, ref byte[] jsonByt
10881090
return EndToken(sb);
10891091
}
10901092

1091-
//TODO: replace with a mapping array? This switch is really incomplete.
1093+
// handle escaped characters
10921094
switch (ch)
10931095
{
10941096
case 't':
@@ -1115,15 +1117,21 @@ private static LexToken GetNextTokenInternal(ref int jsonPos, ref byte[] jsonByt
11151117
ch = '\\';
11161118
break;
11171119

1118-
case 'u':
1119-
unicodeEncoded = true;
1120-
break;
1121-
11221120
case '"':
11231121
ch = '"';
11241122
break;
11251123

1124+
case '\'':
1125+
ch = '\'';
1126+
break;
1127+
1128+
case 'u':
1129+
// unicode escape \uXXXX - we'll handle below
1130+
unicodeEncoded = true;
1131+
break;
1132+
11261133
default:
1134+
// unknown escape sequence
11271135
throw new DeserializationException();
11281136
}
11291137
}
@@ -1132,56 +1140,32 @@ private static LexToken GetNextTokenInternal(ref int jsonPos, ref byte[] jsonByt
11321140
{
11331141
if (unicodeEncoded)
11341142
{
1135-
int numberCounter = 0;
1136-
1137-
// next 4 chars have to be numeric
1138-
StringBuilder encodedValue = new();
1139-
1140-
// advance position to next char
1141-
jsonPos++;
1142-
ch = (char)jsonBytes[jsonPos];
1143-
1144-
for (int i = 0; i < 4; i++)
1143+
// We must decode exactly 4 hex digits following the '\u'
1144+
// Ensure there are at least 4 bytes remaining
1145+
if (jsonPos + 4 > jsonBytes.Length)
11451146
{
1146-
if (IsNumberChar(ch))
1147-
{
1148-
numberCounter++;
1149-
1150-
encodedValue.Append(ch);
1151-
1152-
ch = (char)jsonBytes[jsonPos];
1153-
1154-
if (IsNumberChar(ch))
1155-
{
1156-
// We're still working on the number - advance jsonPos
1157-
jsonPos++;
1158-
}
1159-
}
1147+
throw new DeserializationException();
11601148
}
11611149

1162-
if (numberCounter == 4)
1150+
// Read 4 ASCII hex chars (they should be ASCII hex digits)
1151+
int val = 0;
1152+
for (int i = 0; i < 4; i++)
11631153
{
1164-
// we're good with the encoded data
1165-
// try parse number as an UTF-8 char
1166-
try
1167-
{
1168-
// NOTE: the encoded value has hexadecimal format
1169-
int unicodeChar = Convert.ToInt16(encodedValue.ToString(), 16);
1170-
1171-
_ = sb.Append((char)unicodeChar);
1172-
}
1173-
catch
1154+
char hc = (char)jsonBytes[jsonPos++];
1155+
int digit;
1156+
if (hc >= '0' && hc <= '9') digit = hc - '0';
1157+
else if (hc >= 'a' && hc <= 'f') digit = 10 + (hc - 'a');
1158+
else if (hc >= 'A' && hc <= 'F') digit = 10 + (hc - 'A');
1159+
else
11741160
{
1175-
// couldn't parse this number as a valid Unicode value
11761161
throw new DeserializationException();
11771162
}
1163+
1164+
val = (val << 4) + digit;
11781165
}
1179-
else
1180-
{
1181-
// anything else, we can't parse it properly
1182-
// throw exception
1183-
throw new DeserializationException();
1184-
}
1166+
1167+
// Append the decoded unicode character
1168+
sb.Append((char)val);
11851169
}
11861170
else
11871171
{

0 commit comments

Comments
 (0)