public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) { JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options); if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object && type.GetCustomAttribute <DataContractAttribute>() is not null) { jsonTypeInfo.Properties.Clear(); foreach (PropertyInfo propInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (propInfo.GetCustomAttribute <IgnoreDataMemberAttribute>() is not null) { continue; } DataMemberAttribute?attr = propInfo.GetCustomAttribute <DataMemberAttribute>(); JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(propInfo.PropertyType, attr?.Name ?? propInfo.Name); jsonPropertyInfo.Order = attr?.Order ?? 0; jsonPropertyInfo.Get = propInfo.CanRead ? propInfo.GetValue : null; jsonPropertyInfo.Set = propInfo.CanWrite ? propInfo.SetValue : null; jsonTypeInfo.Properties.Add(jsonPropertyInfo); } } return(jsonTypeInfo); }
private static void TestTypeInfoImmutability <T>(JsonTypeInfo <T> typeInfo) { JsonTypeInfo untyped = typeInfo; Assert.Equal(typeof(T), typeInfo.Type); Assert.True(typeInfo.Converter.CanConvert(typeof(T))); JsonPropertyInfo prop = typeInfo.CreateJsonPropertyInfo(typeof(string), "foo"); Assert.True(typeInfo.Properties.IsReadOnly); Assert.Throws <InvalidOperationException>(() => untyped.CreateObject = untyped.CreateObject); Assert.Throws <InvalidOperationException>(() => typeInfo.CreateObject = typeInfo.CreateObject); Assert.Throws <InvalidOperationException>(() => typeInfo.NumberHandling = typeInfo.NumberHandling); Assert.Throws <InvalidOperationException>(() => typeInfo.Properties.Clear()); Assert.Throws <InvalidOperationException>(() => typeInfo.Properties.Add(prop)); Assert.Throws <InvalidOperationException>(() => typeInfo.Properties.Insert(0, prop)); Assert.Throws <InvalidOperationException>(() => typeInfo.PolymorphismOptions = null); Assert.Throws <InvalidOperationException>(() => typeInfo.PolymorphismOptions = new()); if (typeInfo.PolymorphismOptions is JsonPolymorphismOptions jpo) { Assert.True(jpo.DerivedTypes.IsReadOnly); Assert.Throws <InvalidOperationException>(() => jpo.IgnoreUnrecognizedTypeDiscriminators = true); Assert.Throws <InvalidOperationException>(() => jpo.TypeDiscriminatorPropertyName = "__case"); Assert.Throws <InvalidOperationException>(() => jpo.UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor); Assert.Throws <InvalidOperationException>(() => jpo.DerivedTypes.Clear()); Assert.Throws <InvalidOperationException>(() => jpo.DerivedTypes.Add(default));
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) { JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options); if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object && type.GetCustomAttribute <DataContractAttribute>() is not null) { jsonTypeInfo.Properties.Clear(); // TODO should not require clearing IEnumerable <(PropertyInfo propInfo, DataMemberAttribute attr)> properties = type .GetProperties(BindingFlags.Instance | BindingFlags.Public) .Where(propInfo => propInfo.GetCustomAttribute <IgnoreDataMemberAttribute>() is null) .Select(propInfo => (propInfo, attr: propInfo.GetCustomAttribute <DataMemberAttribute>())) .OrderBy(entry => entry.attr?.Order ?? 0); foreach ((PropertyInfo propertyInfo, DataMemberAttribute? attr) in properties) { JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(propertyInfo.PropertyType, attr?.Name ?? propertyInfo.Name); jsonPropertyInfo.Get = propertyInfo.CanRead ? propertyInfo.GetValue : null; jsonPropertyInfo.Set = propertyInfo.CanWrite ? propertyInfo.SetValue : null; jsonTypeInfo.Properties.Add(jsonPropertyInfo); } } return(jsonTypeInfo); }
public static void AddingPropertyToNonObjectJsonTypeInfoKindThrows(Type type, JsonTypeInfoKind expectedKind) { JsonSerializerOptions options = new(); DefaultJsonTypeInfoResolver resolver = new(); JsonTypeInfo typeInfo = resolver.GetTypeInfo(type, options); Assert.Equal(expectedKind, typeInfo.Kind); JsonPropertyInfo property = typeInfo.CreateJsonPropertyInfo(typeof(int), "test"); Assert.Throws <InvalidOperationException>(() => typeInfo.Properties.Add(property)); }
private JsonPropertyInfo CreatePropertyInfo(JsonTypeInfo typeInfo, string name, FieldDescriptor field, bool isSerializable) { var propertyInfo = typeInfo.CreateJsonPropertyInfo( JsonConverterHelper.GetFieldType(field), name); // Properties that don't have this flag set are only used to deserialize incoming JSON. if (isSerializable) { propertyInfo.ShouldSerialize = (o, v) => { return(JsonConverterHelper.ShouldFormatFieldValue((IMessage)o, field, v, !_context.Settings.IgnoreDefaultValues)); }; propertyInfo.Get = (o) => { return(field.Accessor.GetValue((IMessage)o)); }; } propertyInfo.Set = GetSetMethod(field); return(propertyInfo); }
public static void TypeInfoPropertiesDefaults(Type type) { bool usingParametrizedConstructor = type.GetConstructors() .FirstOrDefault(ctor => ctor.GetParameters().Length != 0 && ctor.GetCustomAttribute <JsonConstructorAttribute>() != null) != null; DefaultJsonTypeInfoResolver r = new(); JsonSerializerOptions o = new(); o.Converters.Add(new CustomThrowingConverter <SomeClass>()); JsonTypeInfo ti = r.GetTypeInfo(type, o); Assert.Same(o, ti.Options); Assert.NotNull(ti.Properties); if (ti.Kind == JsonTypeInfoKind.Object && usingParametrizedConstructor) { Assert.Null(ti.CreateObject); Func <object> createObj = () => Activator.CreateInstance(type); ti.CreateObject = createObj; Assert.Same(createObj, ti.CreateObject); } else if (ti.Kind == JsonTypeInfoKind.None) { Assert.Null(ti.CreateObject); Assert.Throws <InvalidOperationException>(() => ti.CreateObject = () => Activator.CreateInstance(type)); } else { Assert.NotNull(ti.CreateObject); Func <object> createObj = () => Activator.CreateInstance(type); ti.CreateObject = createObj; Assert.Same(createObj, ti.CreateObject); } JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), "foo"); Assert.NotNull(property); if (ti.Kind == JsonTypeInfoKind.Object) { Assert.InRange(ti.Properties.Count, 1, 10); Assert.False(ti.Properties.IsReadOnly); ti.Properties.Add(property); ti.Properties.Remove(property); } else { Assert.Equal(0, ti.Properties.Count); Assert.True(ti.Properties.IsReadOnly); Assert.Throws <InvalidOperationException>(() => ti.Properties.Add(property)); Assert.Throws <InvalidOperationException>(() => ti.Properties.Insert(0, property)); Assert.Throws <InvalidOperationException>(() => ti.Properties.Clear()); } Assert.Null(ti.NumberHandling); JsonNumberHandling numberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString; ti.NumberHandling = numberHandling; Assert.Equal(numberHandling, ti.NumberHandling); InvokeGeneric(type, nameof(TypeInfoPropertiesDefaults_Generic), ti); }
static void CreatePropertyAndCheckOptions(JsonSerializerOptions expectedOptions, JsonTypeInfo typeInfo) { JsonPropertyInfo propertyInfo = typeInfo.CreateJsonPropertyInfo(typeof(string), "test"); Assert.Same(expectedOptions, propertyInfo.Options); }
public static void CombineCustomResolverWithDefault() { TestResolver resolver = new TestResolver((Type type, JsonSerializerOptions options) => { if (type != typeof(TestClass)) { return(null); } JsonTypeInfo <TestClass> ti = JsonTypeInfo.CreateJsonTypeInfo <TestClass>(options); ti.CreateObject = () => new TestClass() { TestField = string.Empty, TestProperty = 42, }; JsonPropertyInfo field = ti.CreateJsonPropertyInfo(typeof(string), "MyTestField"); field.Get = (o) => { TestClass obj = (TestClass)o; return(obj.TestField ?? string.Empty); }; field.Set = (o, val) => { TestClass obj = (TestClass)o; string value = (string?)val ?? string.Empty; obj.TestField = value; }; field.ShouldSerialize = (o, val) => (string)val != string.Empty; JsonPropertyInfo prop = ti.CreateJsonPropertyInfo(typeof(int), "MyTestProperty"); prop.Get = (o) => { TestClass obj = (TestClass)o; return(obj.TestProperty); }; prop.Set = (o, val) => { TestClass obj = (TestClass)o; obj.TestProperty = (int)val; }; prop.ShouldSerialize = (o, val) => (int)val != 42; ti.Properties.Add(field); ti.Properties.Add(prop); return(ti); }); JsonSerializerOptions options = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver() }; options.IncludeFields = true; options.TypeInfoResolver = JsonTypeInfoResolver.Combine(resolver, options.TypeInfoResolver); TestClass originalObj = new TestClass() { TestField = "test value", TestProperty = 45, }; string json = JsonSerializer.Serialize(originalObj, options); Assert.Equal(@"{""MyTestField"":""test value"",""MyTestProperty"":45}", json); TestClass deserialized = JsonSerializer.Deserialize <TestClass>(json, options); Assert.Equal(originalObj.TestField, deserialized.TestField); Assert.Equal(originalObj.TestProperty, deserialized.TestProperty); originalObj.TestField = null; json = JsonSerializer.Serialize(originalObj, options); Assert.Equal(@"{""MyTestProperty"":45}", json); originalObj.TestField = string.Empty; json = JsonSerializer.Serialize(originalObj, options); Assert.Equal(@"{""MyTestProperty"":45}", json); deserialized = JsonSerializer.Deserialize <TestClass>(json, options); Assert.Equal(originalObj.TestField, deserialized.TestField); Assert.Equal(originalObj.TestProperty, deserialized.TestProperty); originalObj.TestField = "test value"; originalObj.TestProperty = 42; json = JsonSerializer.Serialize(originalObj, options); Assert.Equal(@"{""MyTestField"":""test value""}", json); deserialized = JsonSerializer.Deserialize <TestClass>(json, options); Assert.Equal(originalObj.TestField, deserialized.TestField); Assert.Equal(originalObj.TestProperty, deserialized.TestProperty); }