Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Address feedback & add one more test
  • Loading branch information
eiriktsarpalis committed Jul 7, 2022
commit 9f78a9500217d7279f0a53f52076a44fb93fa936
4 changes: 2 additions & 2 deletions src/libraries/System.Text.Json/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,10 @@
<value>The converter '{0}' is not compatible with the type '{1}'.</value>
</data>
<data name="ResolverTypeNotCompatible" xml:space="preserve">
<value>TypeInfoResolver expected to return JsonTypeInfo of type '{0}' but returned JsonTypeInfo of type '{1}'.</value>
<value>The IJsonTypeInfoResolver returned an incompatible JsonTypeInfo instance of type '{0}', expected type '{1}'.</value>
</data>
<data name="ResolverTypeInfoOptionsNotCompatible" xml:space="preserve">
<value>TypeInfoResolver expected to return JsonTypeInfo options bound to the JsonSerializerOptions provided in the argument.</value>
<value>The IJsonTypeInfoResolver returned a JsonTypeInfo instance whose JsonSerializerOptions setting does not match the provided argument.</value>
</data>
<data name="SerializationConverterWrite" xml:space="preserve">
<value>The converter '{0}' wrote too much or not enough.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public JsonSerializerOptions Options

internal set
{
Debug.Assert(!value.IsLockedInstance);
value.TypeInfoResolver = this;
value.IsLockedInstance = true;
_options = value;
Expand Down Expand Up @@ -103,6 +104,7 @@ protected JsonSerializerContext(JsonSerializerOptions? options)
{
if (options != null)
{
options.VerifyMutable();
Options = options;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,9 @@ internal void InitializeForReflectionSerializer()
{
if (!_isInitializedForReflectionSerializer)
{
DefaultJsonTypeInfoResolver defaultResolver = DefaultJsonTypeInfoResolver.RootDefaultInstance();
_typeInfoResolver ??= defaultResolver;
IsLockedInstance = true;
_typeInfoResolver ??= DefaultJsonTypeInfoResolver.RootDefaultInstance();
InitializeCachingContext();

if (_cachingContext.Options != this)
Expand Down Expand Up @@ -711,7 +712,7 @@ internal JsonWriterOptions GetWriterOptions()
};
}

private void VerifyMutable()
internal void VerifyMutable()
{
if (_isLockedInstance)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static void ThrowInvalidOperationException_SerializationConverterNotCompa
[DoesNotReturn]
public static void ThrowInvalidOperationException_ResolverTypeNotCompatible(Type requestedType, Type actualType)
{
throw new InvalidOperationException(SR.Format(SR.ResolverTypeNotCompatible, requestedType, actualType));
throw new InvalidOperationException(SR.Format(SR.ResolverTypeNotCompatible, actualType, requestedType));
}

[DoesNotReturn]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1101,5 +1101,24 @@ private class RecursiveType
public int Value { get; set; }
public RecursiveType? Next { get; set; }
}

[Fact]
public static void CreateJsonTypeInfo_ClassWithConverterAttribute_ShouldNotResolveConverterAttribute()
{
JsonTypeInfo jsonTypeInfo = JsonTypeInfo.CreateJsonTypeInfo(typeof(ClassWithConverterAttribute), JsonSerializerOptions.Default);
Assert.Equal(typeof(ClassWithConverterAttribute), jsonTypeInfo.Type);
Assert.IsNotType<ClassWithConverterAttribute.CustomConverter>(jsonTypeInfo.Converter);
}


[JsonConverter(typeof(CustomConverter))]
public class ClassWithConverterAttribute
{
public class CustomConverter : JsonConverter<ClassWithConverterAttribute>
{
public override ClassWithConverterAttribute? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException();
public override void Write(Utf8JsonWriter writer, ClassWithConverterAttribute value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -439,20 +439,30 @@ public static void Options_JsonSerializerContext_DoesNotFallbackToReflection()
JsonSerializer.Serialize(new WeatherForecastWithPOCOs(), options); // type supported by context should succeed serialization

var unsupportedValue = new MyClass();
Assert.Null(JsonContext.Default.GetTypeInfo(unsupportedValue.GetType()));
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(unsupportedValue, unsupportedValue.GetType(), JsonContext.Default));
Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(unsupportedValue, options));
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void Options_JsonSerializerContext_DoesNotFallbackToReflection_GetConverter()
public static void Options_JsonSerializerContext_GetConverter_FallsBackToReflectionConverter()
{
RemoteExecutor.Invoke(static () =>
{
var options = JsonContext.Default.Options;
JsonSerializer.Serialize(new WeatherForecastWithPOCOs(), options); // type supported by context should succeed serialization

JsonContext context = JsonContext.Default;
var unsupportedValue = new MyClass();
Assert.Throws<NotSupportedException>(() => options.GetConverter(unsupportedValue.GetType()));

// Default converters have not been rooted yet
Assert.Null(context.GetTypeInfo(typeof(MyClass)));
Assert.Throws<NotSupportedException>(() => context.Options.GetConverter(typeof(MyClass)));

// Root converters process-wide by calling a Serialize overload accepting options
Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(unsupportedValue, context.Options));

// We still can't resolve metadata for MyClass, but we can now resolve a converter using the rooted converters.
Assert.Null(context.GetTypeInfo(typeof(MyClass)));
Assert.IsAssignableFrom<JsonConverter<MyClass>>(context.Options.GetConverter(typeof(MyClass)));

}).Dispose();
}

Expand All @@ -464,8 +474,8 @@ public static void Options_JsonSerializerContext_Combine_FallbackToReflection()
TypeInfoResolver = JsonTypeInfoResolver.Combine(JsonContext.Default, new DefaultJsonTypeInfoResolver())
};

var unsupportedValue = new MyClass();
string json = JsonSerializer.Serialize(unsupportedValue, options);
var value = new MyClass();
string json = JsonSerializer.Serialize(value, options);
JsonTestHelper.AssertJsonEqual("""{"Value":null,"Thing":null}""", json);
}

Expand Down