Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 30 additions & 75 deletions src/Microsoft.IdentityModel.Tokens/Json/JsonSerializerPrimitives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ internal static bool IsReaderAtTokenType(ref Utf8JsonReader reader, JsonTokenTyp

internal static bool ReadBoolean(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// The parameter 'read' can be used by callers reader position the reader to the next token.
// The parameter 'read' can be used by callers to position the reader to the next token.
// This is a convenience when the reader is positioned on a JsonTokenType.PropertyName.
// The caller does not have to make the calls: reader.Read(), JsonSerializerPrimitives.ReadBoolean.
if (read)
Expand All @@ -513,9 +513,6 @@ internal static bool ReadBoolean(ref Utf8JsonReader reader, string propertyName,
if (reader.TokenType == JsonTokenType.True || reader.TokenType == JsonTokenType.False)
{
bool retVal = reader.GetBoolean();

// move to next token.
reader.Read();
return retVal;
}

Expand All @@ -525,7 +522,7 @@ internal static bool ReadBoolean(ref Utf8JsonReader reader, string propertyName,

internal static long ReadLong(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// The parameter 'read' can be used by callers reader position the reader to the next token.
// The parameter 'read' can be used by callers to position the reader to the next token.
// This is a convenience when the reader is positioned on a JsonTokenType.PropertyName.
// The caller does not have to make the calls: reader.Read(), JsonSerializerPrimitives.ReadBoolean.
if (read)
Expand Down Expand Up @@ -561,8 +558,6 @@ internal static long ReadLong(ref Utf8JsonReader reader, string propertyName, st
CreateJsonReaderException(ref reader, "JsonTokenType.Number", className, propertyName));
}

// move to next token.
reader.Read();
return retVal;
}

Expand Down Expand Up @@ -610,7 +605,15 @@ internal static List<object> ReadArrayOfObjects(ref Utf8JsonReader reader, strin
|| reader.TokenType == JsonTokenType.String
|| reader.TokenType == JsonTokenType.StartObject
|| reader.TokenType == JsonTokenType.StartArray)
{
// For StartObject/StartArray: ReadPropertyValueAsObject calls ReadJsonElement which
// already advances past the complex value. For scalar types (Null, Number, String):
// ReadPropertyValueAsObject leaves the reader AT the value, so we advance explicitly.
bool isComplex = reader.TokenType == JsonTokenType.StartObject || reader.TokenType == JsonTokenType.StartArray;
objects.Add(ReadPropertyValueAsObject(ref reader, propertyName, className));
if (!isComplex)
reader.Read();
}
else if (!reader.Read())
break;
}
Expand Down Expand Up @@ -639,23 +642,20 @@ internal static string ReadPropertyName(ref Utf8JsonReader reader, string classN
internal static string ReadString(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// returning null keeps the same logic as JsonSerialization.ReadObject
if (IsReaderPositionedOnNull(ref reader, read, true))
if (IsReaderPositionedOnNull(ref reader, read, read))
return null;

if (!IsReaderAtTokenType(ref reader, JsonTokenType.String, false))
throw LogHelper.LogExceptionMessage(
CreateJsonReaderExceptionInvalidType(ref reader, "JsonTokenType.String", className, propertyName));

string retval = reader.GetString();

// move to next token.
reader.Read();
return retval;
}

internal static string ReadStringAsBool(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// The parameter 'read' can be used by callers reader position the reader to the next token.
// The parameter 'read' can be used by callers to position the reader to the next token.
// This is a convenience when the reader is positioned on a JsonTokenType.PropertyName.
// The caller does not have to make the calls: reader.Read(), JsonSerializerPrimitives.ReadBoolean.
if (read)
Expand All @@ -667,11 +667,7 @@ internal static string ReadStringAsBool(ref Utf8JsonReader reader, string proper

string strValue = reader.GetString();
if (bool.TryParse(strValue, out bool boolValue))
{
// move to next token.
reader.Read();
return boolValue ? True : False;
}

throw LogHelper.LogExceptionMessage(CreateJsonReaderException(ref reader, "JsonTokenType.Boolean", className, propertyName));
}
Expand All @@ -687,7 +683,7 @@ internal static string ReadStringAsBool(ref Utf8JsonReader reader, string proper
internal static string ReadStringOrNumberAsString(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// returning null keeps the same logic as JsonSerialization.ReadObject
if (IsReaderPositionedOnNull(ref reader, read, true))
if (IsReaderPositionedOnNull(ref reader, read, read))
return null;

if (reader.TokenType == JsonTokenType.Number)
Expand All @@ -698,9 +694,6 @@ internal static string ReadStringOrNumberAsString(ref Utf8JsonReader reader, str
CreateJsonReaderException(ref reader, "JsonTokenType.String or JsonTokenType.Number", className, propertyName));

string retVal = reader.GetString();

// move to next token.
reader.Read();
return retVal;
}

Expand Down Expand Up @@ -816,7 +809,7 @@ internal static bool IsKnownToNotBeDateTime(string claimType)
internal static object ReadStringAsObject(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// returning null keeps the same logic as JsonSerialization.ReadObject
if (IsReaderPositionedOnNull(ref reader, read, true))
if (IsReaderPositionedOnNull(ref reader, read, read))
return null;

if (reader.TokenType != JsonTokenType.String)
Expand All @@ -826,10 +819,7 @@ internal static object ReadStringAsObject(ref Utf8JsonReader reader, string prop
string originalString = reader.GetString();

if (!AppContextSwitches.TryAllStringClaimsAsDateTime && IsKnownToNotBeDateTime(propertyName))
{
reader.Read();
return originalString;
}

#pragma warning disable CA1031 // Do not catch general exception types
try
Expand All @@ -847,8 +837,6 @@ internal static object ReadStringAsObject(ref Utf8JsonReader reader, string prop
{ }
#pragma warning restore CA1031 // Do not catch general exception types

// move to next token.
reader.Read();
return originalString;
}

Expand All @@ -860,7 +848,7 @@ internal static ICollection<string> ReadStrings(
bool read = false)
{
// returning null keeps the same logic as JsonSerialization.ReadObject
if (IsReaderPositionedOnNull(ref reader, read, true))
if (IsReaderPositionedOnNull(ref reader, read, read))
return null;

// Expect the reader to be at a JsonTokenType.StartArray.
Expand All @@ -871,9 +859,12 @@ internal static ICollection<string> ReadStrings(
while (true)
{
if (reader.TokenType == JsonTokenType.String)
{
strings.Add(ReadString(ref reader, propertyName, className));
// We read a JsonTokenType.StartArray above, exiting and positioning reader at next token.
else if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, true))
reader.Read();
}
// We read a JsonTokenType.StartArray above, exiting and positioning reader at next token only when read=true.
else if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, read))
break;
else if (!reader.Read())
break;
Expand All @@ -890,7 +881,7 @@ internal static IList<string> ReadStrings(
bool read = false)
{
// returning null keeps the same logic as JsonSerialization.ReadObject
if (IsReaderPositionedOnNull(ref reader, read, true))
if (IsReaderPositionedOnNull(ref reader, read, read))
return null;

if (!IsReaderAtTokenType(ref reader, JsonTokenType.StartArray, true))
Expand All @@ -899,11 +890,12 @@ internal static IList<string> ReadStrings(

while (true)
{
// We read a JsonTokenType.StartArray above, exiting and positioning reader at next token.
if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, true))
// We read a JsonTokenType.StartArray above, exiting and positioning reader at next token only when read=true.
if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, read))
break;

strings.Add(ReadString(ref reader, propertyName, className));
reader.Read();
}

return strings;
Expand All @@ -916,7 +908,7 @@ internal static void ReadStringsSkipNulls(
string propertyName,
string className)
{
if (IsReaderPositionedOnNull(ref reader, false, true))
if (IsReaderPositionedOnNull(ref reader, false, false))
return;

if (!IsReaderAtTokenType(ref reader, JsonTokenType.StartArray, true))
Expand All @@ -925,8 +917,8 @@ internal static void ReadStringsSkipNulls(

while (true)
{
// We read a JsonTokenType.StartArray above, exiting and positioning reader at next token.
if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, true))
// We read a JsonTokenType.StartArray above, leaving reader at EndArray (not advancing past it).
if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, false))
break;

if (reader.TokenType == JsonTokenType.Null)
Expand All @@ -937,9 +929,8 @@ internal static void ReadStringsSkipNulls(
}

strings.Add(ReadString(ref reader, propertyName, className));
reader.Read();
}

return;
}

/// <summary>
Expand All @@ -952,27 +943,21 @@ internal static void ReadStringsSkipNulls(
/// <returns>The property value from the reader as an object.</returns>
internal static object ReadPropertyValueAsObject(ref Utf8JsonReader reader, string propertyName, string className, bool read = false)
{
// The parameter 'read' can be used by callers reader position the reader to the next token.
// The parameter 'read' can be used by callers to position the reader to the next token.
// This is a convenience when the reader is positioned on a JsonTokenType.PropertyName.
// The caller does not have to make the calls: reader.Read(), JsonSerializerPrimitives.ReadBoolean.
// The caller does not have to make the calls: reader.Read(), JsonSerializerPrimitives.ReadPropertyValueAsObject.
if (read)
reader.Read();

switch (reader.TokenType)
{
case JsonTokenType.False:
// move to next token.
reader.Read();
return false;
case JsonTokenType.Number:
return ReadNumber(ref reader);
case JsonTokenType.True:
// move to next token.
reader.Read();
return true;
case JsonTokenType.Null:
// move to next token.
reader.Read();
return null;
case JsonTokenType.String:
return ReadStringAsObject(ref reader, propertyName, className);
Expand All @@ -982,56 +967,26 @@ internal static object ReadPropertyValueAsObject(ref Utf8JsonReader reader, stri
return ReadJsonElement(ref reader);
default:
// The reader is pointing at a token that we don't know how to handle.
// move to next token.
reader.Read();
return null;
}
}

internal static object ReadNumber(ref Utf8JsonReader reader)
{
if (reader.TryGetInt32(out int i))
{
// move to next token.
reader.Read();
return i;
}
else if (reader.TryGetInt64(out long l))
{
// move to next token.
reader.Read();
return l;
}
else if (reader.TryGetDouble(out double d))
{
// move to next token.
reader.Read();
return d;
}
else if (reader.TryGetUInt32(out uint u))
{
// move to next token.
reader.Read();
return u;
}
else if (reader.TryGetUInt64(out ulong ul))
{
// move to next token.
reader.Read();
return ul;
}
else if (reader.TryGetSingle(out float f))
{
// move to next token.
reader.Read();
return f;
}
else if (reader.TryGetDecimal(out decimal m))
{
// move to next token.
reader.Read();
return m;
}

Debug.Assert(false, "expected to read a number, but none of the Utf8JsonReader.TryGet... methods returned true.");

Expand Down
Loading
Loading