Search code examples
xamarin.androidsystem.text.json.net-7.0

Serializing/Deserializing an object that is derived from Java.Lang.Object throws exception (using System.Text.Json)


In one of my .net7-android project, I am trying to serialize an object using System.Text.Json. My object is derived from Java.Lang.Object. I am not intrested in serializing/deserializing the base class (Java.Lang.Object).

The exception I am getting is "Serialization and deserialization of 'System.Type' instances are not supported.". Anyone has any ideas how can it be fixed?


Solution

  • One of the public properties declared by Java.Lang.Object must (directly or indirectly) return an object of type System.Type, thereby causing the exception. Since you don't want to serialize any of these properties anyway, you could create a custom JsonTypeInfo modifier that excludes all properties declared by Java.Lang.Object.

    First, define the following extension methods:

    public static class JsonExtensions
    {
        public static Action<JsonTypeInfo> IgnorePropertiesDeclaredBy(Type declaringType)
            => (Action<JsonTypeInfo>) (typeInfo => 
                                       {
                                           if (typeInfo.Kind != JsonTypeInfoKind.Object || !declaringType.IsAssignableFrom(typeInfo.Type))
                                               return;
                                           foreach (var property in typeInfo.Properties)
                                               if (property.GetDeclaringType() == declaringType)
                                                   property.ShouldSerialize = static (obj, value) => false;
                                       });
        public static Action<JsonTypeInfo> IgnorePropertiesDeclaredBy<TDeclaringType>() => IgnorePropertiesDeclaredBy(typeof(TDeclaringType));
        public static Type? GetDeclaringType(this JsonPropertyInfo property) => (property.AttributeProvider as MemberInfo)?.DeclaringType;
    }
    

    And now you can use JsonExtensions.IgnorePropertiesDeclaredBy<Java.Lang.Object>() to omit all properties declared by Java.Lang.Object when serializing instances of derived types like so:

    var options = new JsonSerializerOptions
    {
        TypeInfoResolver = new DefaultJsonTypeInfoResolver
        {
            Modifiers = { JsonExtensions.IgnorePropertiesDeclaredBy<Java.Lang.Object>() },
        },
        // Add other options as required
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 
        WriteIndented = true,           
    };
    
    var json = JsonSerializer.Serialize(myJavaObject, options);
    

    Note that this will only suppress properties declared by some base type. Suppressing properties declared by an interface that the type implements is not implemented.

    Demo fiddle using a mockup of Java.Lang.Object here: https://dotnetfiddle.net/8vNQS6.