Skip to content

Instantly share code, notes, and snippets.

@steveharter
Last active February 1, 2021 18:58
Show Gist options
  • Save steveharter/3457e870f8876fa2245dcf71f56b2b8d to your computer and use it in GitHub Desktop.
Save steveharter/3457e870f8876fa2245dcf71f56b2b8d to your computer and use it in GitHub Desktop.
JSON extensibility improvements

Main issue:More extensible object and collection converters

One common aspect is being able to change serialization options on a per-type basis, but without per-type converters or custom attributes. This would be implemented as a virtual method that can be overridden to expose or create the "metadata" classes including JsonClassInfo and JsonPropertyInfo.

This could be achieved by making JsonSerializerOptions non-sealed and adding virtual methods like:

protected JsonClassInfo GetJsonClassInfo(Type type);

However, with the planned work on code-gen and the JsonContext class similar behavior is already there in the form of:

public virtual JsonClassInfo? GetJsonClassInfo(Type type);

In addition, the JsonContext class will be able to passed to new (De)Serialize methods and replaces JsonSerializerOptions since the context class holds a reference to an options instance. A JsonContext can either share an options instance (by a consumer creating the Context class), or configure its own (by the author of the context).

Having the extensibility on the context class instead of the options class allows more fine-grain control over an area of code that may have different requirements from other areas. For example, a third party library may expose a context class that has its own unique property naming policy.

GetJsonClassInfo() allows to metadata to be overwritten for class, but to change property-level a sample would do:

// This is generated
public class CodeGeneratedContext : JsonContext {...}

A consumer could change the settings:

public class MyOverrideContext : CodeGeneratedContext {...}
{
    public virtual JsonClassInfo? GetJsonClassInfo(Type type)
    {
        JsonClassInfo classInfo = base.GetJsonClassInfo();
        foreach (JsonPropertyInfo property in classInfo.GetProperties)
        {
            if (property.Type == typeof)
            
        }
    }
}

However, for the fast-path option where the context is manually created we need to determine if there is an override... Having a non-null delegate approach may be better, plus perhaps support multicast delegates

Equivalent of DefaultContractResolver in System.Text.Json

https://stackoverflow.com/questions/59792850/system-text-json-serialize-null-strings-into-empty-strings-globally

  • Ignoring empty collections on serialize
    • Currently we have support for null, default
    • A converter can be written for empty string
    • CreateProperty() called which returns "false" for CanSerialize
  • I use it to hide GDPR sensitive data depending on requestor permissions.
  • NHibernate Proxy objects serialization:
public class NHibernateContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override JsonContract CreateContract(Type objectType)
        {
            if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType))
            {
                return base.CreateContract(objectType.BaseType);
            }
            else
            {
                return base.CreateContract(objectType);
            }
        }
    }
  • Please at least support writing custom converter for System.Data.DataTable and System.Data.DataRow. Current JsonConverter is intended primarily for data types, not full\complex objects.

Requirements for JsonSerializerContext

Create independently (have own options)

Being able to modify options or specify

Virtual method to create ClassInfo

per property override?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment