Json parsing fixes

Fix parsing empty arrays and objects containing spaces
See ORelio/Sharp-Tools#1 for more details
This commit is contained in:
ORelio 2020-12-24 14:30:14 +01:00
parent 8aee0cb731
commit e06438b582

View file

@ -7,7 +7,7 @@ namespace MinecraftClient
{ {
/// <summary> /// <summary>
/// This class parses JSON data and returns an object describing that data. /// This class parses JSON data and returns an object describing that data.
/// Really lightweight JSON handling by ORelio - (c) 2013 - 2014 /// Really lightweight JSON handling by ORelio - (c) 2013 - 2020
/// </summary> /// </summary>
public static class Json public static class Json
{ {
@ -51,12 +51,14 @@ namespace MinecraftClient
try try
{ {
JSONData data; JSONData data;
SkipSpaces(toparse, ref cursorpos);
switch (toparse[cursorpos]) switch (toparse[cursorpos])
{ {
//Object //Object
case '{': case '{':
data = new JSONData(JSONData.DataType.Object); data = new JSONData(JSONData.DataType.Object);
cursorpos++; cursorpos++;
SkipSpaces(toparse, ref cursorpos);
while (toparse[cursorpos] != '}') while (toparse[cursorpos] != '}')
{ {
if (toparse[cursorpos] == '"') if (toparse[cursorpos] == '"')
@ -75,6 +77,7 @@ namespace MinecraftClient
case '[': case '[':
data = new JSONData(JSONData.DataType.Array); data = new JSONData(JSONData.DataType.Array);
cursorpos++; cursorpos++;
SkipSpaces(toparse, ref cursorpos);
while (toparse[cursorpos] != ']') while (toparse[cursorpos] != ']')
{ {
if (toparse[cursorpos] == ',') { cursorpos++; } if (toparse[cursorpos] == ',') { cursorpos++; }
@ -95,10 +98,10 @@ namespace MinecraftClient
try //Unicode character \u0123 try //Unicode character \u0123
{ {
if (toparse[cursorpos + 1] == 'u' if (toparse[cursorpos + 1] == 'u'
&& isHex(toparse[cursorpos + 2]) && IsHex(toparse[cursorpos + 2])
&& isHex(toparse[cursorpos + 3]) && IsHex(toparse[cursorpos + 3])
&& isHex(toparse[cursorpos + 4]) && IsHex(toparse[cursorpos + 4])
&& isHex(toparse[cursorpos + 5])) && IsHex(toparse[cursorpos + 5]))
{ {
//"abc\u0123abc" => "0123" => 0123 => Unicode char n°0123 => Add char to string //"abc\u0123abc" => "0123" => 0123 => Unicode char n°0123 => Add char to string
data.StringValue += char.ConvertFromUtf32(int.Parse(toparse.Substring(cursorpos + 2, 4), System.Globalization.NumberStyles.HexNumber)); data.StringValue += char.ConvertFromUtf32(int.Parse(toparse.Substring(cursorpos + 2, 4), System.Globalization.NumberStyles.HexNumber));
@ -164,16 +167,21 @@ namespace MinecraftClient
if (toparse[cursorpos] == 'e') { cursorpos++; data.StringValue = "false"; } if (toparse[cursorpos] == 'e') { cursorpos++; data.StringValue = "false"; }
break; break;
//Null field
case 'n':
data = new JSONData(JSONData.DataType.String);
cursorpos++;
if (toparse[cursorpos] == 'u') { cursorpos++; }
if (toparse[cursorpos] == 'l') { cursorpos++; }
if (toparse[cursorpos] == 'l') { cursorpos++; data.StringValue = "null"; }
break;
//Unknown data //Unknown data
default: default:
cursorpos++; cursorpos++;
return String2Data(toparse, ref cursorpos); return String2Data(toparse, ref cursorpos);
} }
while (cursorpos < toparse.Length SkipSpaces(toparse, ref cursorpos);
&& (char.IsWhiteSpace(toparse[cursorpos])
|| toparse[cursorpos] == '\r'
|| toparse[cursorpos] == '\n'))
cursorpos++;
return data; return data;
} }
catch (IndexOutOfRangeException) catch (IndexOutOfRangeException)
@ -183,10 +191,24 @@ namespace MinecraftClient
} }
/// <summary> /// <summary>
/// Small function for checking if a char is an hexadecimal char (0-9 A-F a-f) /// Check if a char is an hexadecimal char (0-9 A-F a-f)
/// </summary> /// </summary>
/// <param name="c">Char to test</param> /// <param name="c">Char to test</param>
/// <returns>True if hexadecimal</returns> /// <returns>True if hexadecimal</returns>
private static bool isHex(char c) { return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); } private static bool IsHex(char c) { return ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); }
/// <summary>
/// Advance the cursor to skip white spaces and line breaks
/// </summary>
/// <param name="toparse">String to parse</param>
/// <param name="cursorpos">Cursor position to update</param>
private static void SkipSpaces(string toparse, ref int cursorpos)
{
while (cursorpos < toparse.Length
&& (char.IsWhiteSpace(toparse[cursorpos])
|| toparse[cursorpos] == '\r'
|| toparse[cursorpos] == '\n'))
cursorpos++;
}
} }
} }