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);
            }
Example #2
0
        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));
Example #3
0
            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);
            }
Example #4
0
        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));
        }
Example #5
0
    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);
    }
Example #6
0
        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);
        }
Example #7
0
            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);
        }