}
catch (JsonReaderException ex)
{
- ThrowHelper.ReThrowWithPath(state, ex);
+ ThrowHelper.ReThrowWithPath(ref state, ex);
return default;
}
catch (FormatException ex) when (ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
{
- ThrowHelper.ReThrowWithPath(state, reader, ex);
+ ThrowHelper.ReThrowWithPath(ref state, reader, ex);
return default;
}
catch (InvalidOperationException ex) when (ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
{
- ThrowHelper.ReThrowWithPath(state, reader, ex);
+ ThrowHelper.ReThrowWithPath(ref state, reader, ex);
return default;
}
- catch (JsonException ex)
+ catch (JsonException ex) when (ex.Path == null)
{
- ThrowHelper.AddJsonExceptionInformation(state, reader, ex);
+ // JsonExceptions where the Path property is already set
+ // typically originate from nested calls to JsonSerializer;
+ // treat these cases as any other exception type and do not
+ // overwrite any exception information.
+
+ ThrowHelper.AddJsonExceptionInformation(ref state, reader, ex);
throw;
}
catch (NotSupportedException ex)
throw;
}
- ThrowHelper.ThrowNotSupportedException(state, reader, ex);
+ ThrowHelper.ThrowNotSupportedException(ref state, reader, ex);
return default;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
{
- var ex = new JsonException(SR.Format(SR.DeserializeUnableToConvertValue, propertyType));
- ex.AppendPathInformation = true;
- throw ex;
+ throw new JsonException(SR.Format(SR.DeserializeUnableToConvertValue, propertyType)) { AppendPathInformation = true };
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowJsonException_SerializationConverterRead(JsonConverter? converter)
{
- var ex = new JsonException(SR.Format(SR.SerializationConverterRead, converter));
- ex.AppendPathInformation = true;
- throw ex;
+ throw new JsonException(SR.Format(SR.SerializationConverterRead, converter)) { AppendPathInformation = true };
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowJsonException_SerializationConverterWrite(JsonConverter? converter)
{
- var ex = new JsonException(SR.Format(SR.SerializationConverterWrite, converter));
- ex.AppendPathInformation = true;
- throw ex;
+ throw new JsonException(SR.Format(SR.SerializationConverterWrite, converter)) { AppendPathInformation = true };
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowJsonException_SerializerCycleDetected(int maxDepth)
{
- throw new JsonException(SR.Format(SR.SerializerCycleDetected, maxDepth));
+ throw new JsonException(SR.Format(SR.SerializerCycleDetected, maxDepth)) { AppendPathInformation = true };
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowJsonException(string? message = null)
{
- JsonException ex;
- if (string.IsNullOrEmpty(message))
- {
- ex = new JsonException();
- }
- else
- {
- ex = new JsonException(message);
- ex.AppendPathInformation = true;
- }
-
- throw ex;
+ throw new JsonException(message) { AppendPathInformation = true };
}
[DoesNotReturn]
NotSupportedException ex = new NotSupportedException(
SR.Format(SR.ObjectWithParameterizedCtorRefMetadataNotHonored, state.Current.JsonTypeInfo.Type));
- ThrowNotSupportedException(state, reader, ex);
+ ThrowNotSupportedException(ref state, reader, ex);
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
- public static void ReThrowWithPath(in ReadStack state, JsonReaderException ex)
+ public static void ReThrowWithPath(ref ReadStack state, JsonReaderException ex)
{
Debug.Assert(ex.Path == null);
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
- public static void ReThrowWithPath(in ReadStack state, in Utf8JsonReader reader, Exception ex)
+ public static void ReThrowWithPath(ref ReadStack state, in Utf8JsonReader reader, Exception ex)
{
JsonException jsonException = new JsonException(null, ex);
- AddJsonExceptionInformation(state, reader, jsonException);
+ AddJsonExceptionInformation(ref state, reader, jsonException);
throw jsonException;
}
- public static void AddJsonExceptionInformation(in ReadStack state, in Utf8JsonReader reader, JsonException ex)
+ public static void AddJsonExceptionInformation(ref ReadStack state, in Utf8JsonReader reader, JsonException ex)
{
+ Debug.Assert(ex.Path is null); // do not overwrite existing path information
+
long lineNumber = reader.CurrentState._lineNumber;
ex.LineNumber = lineNumber;
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
- public static void ReThrowWithPath(in WriteStack state, Exception ex)
+ public static void ReThrowWithPath(ref WriteStack state, Exception ex)
{
JsonException jsonException = new JsonException(null, ex);
- AddJsonExceptionInformation(state, jsonException);
+ AddJsonExceptionInformation(ref state, jsonException);
throw jsonException;
}
- public static void AddJsonExceptionInformation(in WriteStack state, JsonException ex)
+ public static void AddJsonExceptionInformation(ref WriteStack state, JsonException ex)
{
+ Debug.Assert(ex.Path is null); // do not overwrite existing path information
+
string path = state.PropertyPath();
ex.Path = path;
}
[DoesNotReturn]
- public static void ThrowNotSupportedException(in ReadStack state, in Utf8JsonReader reader, NotSupportedException ex)
+ public static void ThrowNotSupportedException(ref ReadStack state, in Utf8JsonReader reader, NotSupportedException ex)
{
string message = ex.Message;
}
[DoesNotReturn]
- public static void ThrowNotSupportedException(in WriteStack state, NotSupportedException ex)
+ public static void ThrowNotSupportedException(ref WriteStack state, NotSupportedException ex)
{
string message = ex.Message;
message = SR.Format(SR.DeserializeNoConstructor, nameof(JsonConstructorAttribute), type);
}
- ThrowNotSupportedException(state, reader, new NotSupportedException(message));
+ ThrowNotSupportedException(ref state, reader, new NotSupportedException(message));
}
[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowNotSupportedException_CannotPopulateCollection(Type type, ref Utf8JsonReader reader, ref ReadStack state)
{
- ThrowNotSupportedException(state, reader, new NotSupportedException(SR.Format(SR.CannotPopulateCollection, type)));
+ ThrowNotSupportedException(ref state, reader, new NotSupportedException(SR.Format(SR.CannotPopulateCollection, type)));
}
[DoesNotReturn]
public StructWithBadCtor_WithProps(SerializationInfo info, StreamingContext ctx) =>
(Info, Ctx) = (info, ctx);
}
+
+ [Fact]
+ public static void CustomConverterThrowingJsonException_Serialization_ShouldNotOverwriteMetadata()
+ {
+ JsonException ex = Assert.Throws<JsonException>(() => JsonSerializer.Serialize(new { Value = new PocoUsingCustomConverterThrowingJsonException() }));
+ Assert.Equal(PocoConverterThrowingCustomJsonException.ExceptionMessage, ex.Message);
+ Assert.Equal(PocoConverterThrowingCustomJsonException.ExceptionPath, ex.Path);
+ }
+
+ [Fact]
+ public static void CustomConverterThrowingJsonException_Deserialization_ShouldNotOverwriteMetadata()
+ {
+ JsonException ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<PocoUsingCustomConverterThrowingJsonException[]>(@"[{}]"));
+ Assert.Equal(PocoConverterThrowingCustomJsonException.ExceptionMessage, ex.Message);
+ Assert.Equal(PocoConverterThrowingCustomJsonException.ExceptionPath, ex.Path);
+ }
+
+ [JsonConverter(typeof(PocoConverterThrowingCustomJsonException))]
+ public class PocoUsingCustomConverterThrowingJsonException
+ {
+ }
+
+ public class PocoConverterThrowingCustomJsonException : JsonConverter<PocoUsingCustomConverterThrowingJsonException>
+ {
+ public const string ExceptionMessage = "Custom JsonException mesage";
+ public const string ExceptionPath = "$.CustomPath";
+
+ public override PocoUsingCustomConverterThrowingJsonException? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ => throw new JsonException(ExceptionMessage, ExceptionPath, 0, 0);
+
+ public override void Write(Utf8JsonWriter writer, PocoUsingCustomConverterThrowingJsonException value, JsonSerializerOptions options)
+ => throw new JsonException(ExceptionMessage, ExceptionPath, 0, 0);
+ }
}
}