Utf8Json Documentation

repository·master·Indexed 25 days ago

https://github.com/neuecc/utf8json

A high-performance, zero-allocation JSON serializer for C# (.NET, .NET Core, Unity, and Xamarin) that reads and writes directly to UTF8 binary to avoid UTF16 string conversion overhead. It provides a high-level JsonSerializer API, low-level JsonReader and JsonWriter structs, and a flexible resolver system via IJsonFormatterResolver for customizing serialization behavior, including support for immutable objects and custom type formatting.

Tokens
7K
Snippets
18
Records
25
Agent score
32%

What's inside Utf8Json

  1. Create a custom CompositeResolver

    master

    For complex projects, it is recommended to build a custom IJsonFormatterResolver that implements a cache for formatters. This allows you to combine specific IJsonFormatter instances (like custom date formatters) with a chain of other resolvers (like ImmutableCollectionResolver or EnumResolver).

    Alternatively, you can use CompositeResolver.Create to build a dynamic resolver at runtime. Note that CompositeResolver.Create has a high cost and cannot be garbage collected easily, so you should store the resulting instance in a static field.

    // create custom composite resolver per project is recommended way.
    public class ProjectDefaultResolver : IJsonFormatterResolver
    {
        public static IJsonFormatterResolver Instance = new ProjectDefaultResolver();
    
        static IJsonFormatter[] formatters = new IJsonFormatter[]{
            new DateTimeFormatter("yyyy-MM-dd HH:mm:ss"),
            new NullableDateTimeFormatter("yyyy-MM-dd HH:mm:ss")
        };
    
        static readonly IJsonFormatterResolver[] resolvers = new[] {
            ImmutableCollectionResolver.Instance,
            EnumResolver.UnderlyingValue,
            StandardResolver.AllowPrivateExcludeNullSnakeCase
        };
    
        // ... implementation of GetFormatter<T> using a FormatterCache ...
    }
    
    // Or create and store dynamic CompositeResolver
    public static class MyOwnProjectResolver
    {
        public static readonly IJsonFormatterResolver Instance = CompositeResolver.Create(
            /* IJsonFormatter[] */,
            /* IJsonFormatterResolver[] */
        );
    }
  2. Configure the IJsonFormatterResolver

    master

    The IJsonFormatterResolver acts as the storage for typed serializers. You can customize serialization behavior by assembling a resolver chain.

    Available Resolvers:

    • BuiltinResolver: Includes primitives, standard classes, nullables, arrays, and lists.
    • DynamicGenericResolver: Handles generic types (e.g., List<T>, Dictionary<K,V>) using reflection on the first call.
    • AttributeFormatterResolver: Resolves formatters based on the [JsonFormatter] attribute.
    • EnumResolver: EnumResolver.Default (serializes as name) or EnumResolver.UnderlyingValue (serializes as value).
    • StandardResolver: A composite resolver that follows the order: object fallback -> builtin -> enum -> dynamic generic -> attribute -> dynamic object.

    StandardResolver can be configured with:

    • AllowPrivate: (bool) If true, uses FormatterServices.GetUninitializedObject to deserialize private fields.
    • ExcludeNull: (bool) If true, skips null properties.
    • NameMutate: (Original, CamelCase, or SnakeCase) Changes the property naming convention.
  3. Customize serialization with Resolvers

    master
    By default, Utf8Json serializes all public members. You can customize the behavior—such as serializing private members, excluding null values, changing the DateTime format (default is ISO8601), or handling enums—by using a Resolver.
  4. Implement conditional property serialization with ShouldSerializeXXX

    master

    Utf8Json supports the ShouldSerialize pattern (similar to Json.NET). If you define a public bool ShouldSerialize<MemberName>() method (must be parameterless), Utf8Json will call it before serializing that member. If the method returns false, the member will be omitted from the output.

    public class MyPerson
    {
        public string Name { get; set; }
        public string[] Addresses { get; set; }
    
    // ShouldSerialize*membername**
        // method must be `public` and return `bool` and parameter less.
        public bool ShouldSerializeAddresses()
        {
            if (Addresses != null && Addresses.Length != 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    
    // {"Name":"foo"}
    JsonSerializer.ToJsonString(new MyPerson { Name = "foo", Addresses = new string[0] });
    
    // {"Name":"bar","Addresses":["tokyo","kyoto"]}
    JsonSerializer.ToJsonString(new MyPerson { Name = "bar", Addresses = new[] { "tokyo", "kyoto" } });
  5. Quickstart with JsonSerializer

    master

    The primary entry point for the library is Utf8Json.JsonSerializer. You can use it to serialize objects to byte arrays, deserialize from byte arrays, convert to strings, or write directly to a stream.

    var p = new Person { Age = 99, Name = "foobar" };
    
    // Object -> byte[] (UTF8)
    byte[] result = JsonSerializer.Serialize(p);
    
    // byte[] -> Object
    var p2 = JsonSerializer.Deserialize<Person>(result);
    
    // Object -> String
    var json = JsonSerializer.ToJsonString(p2);
    
    // Write to Stream
    JsonSerializer.Serialize(stream, p2);
  6. Integrate Utf8Json with AWS Lambda

    master

    To use Utf8Json as a custom serializer in AWS Lambda, implement the Amazon.Lambda.Core.ILambdaSerializer interface. You can pass a custom IJsonFormatterResolver to the constructor to handle specific types (like S3 or Kinesis event records) that require custom formatting.

    // with `Amazon.Lambda.Core package`
    public class Utf8JsonLambdaSerializer : Amazon.Lambda.Core.ILambdaSerializer
    {
        readonly IJsonFormatterResolver resolver;
    
        public Utf8JsonLambdaSerializer()
        {
            this.resolver = JsonSerializer.DefaultResolver;
        }
    
        public Utf8JsonLambdaSerializer(IJsonFormatterResolver resolver)
        {
            this.resolver = resolver;
        }
    
        public void Serialize<T>(T response, Stream responseStream)
        {
            Utf8Json.JsonSerializer.Serialize<T>(responseStream, response, resolver);
        }
    
        public T Deserialize<T>(Stream requestStream)
        {
            return Utf8Json.JsonSerializer.Deserialize<T>(requestStream, resolver);
        }
    }
  7. Serialize custom classes and structs

    master

    Utf8Json can serialize public classes and structs. By default, it serializes all public instance members (fields or properties) using their names as JSON property names.

    To customize serialization:

    • Use [IgnoreDataMember] from System.Runtime.Serialization to exclude a member.
    • Use [DataMember(Name = "...")] from System.Runtime.Serialization to rename a property in the resulting JSON.
    // JsonSerializer.Serialize(new FooBar { FooProperty = 99, BarProperty = "BAR" });
    // Result : {"foo":99}
    public class FooBar
    {
        [DataMember(Name = "foo")]
        public int FooProperty { get; set; }
    
        [IgnoreDataMember]
        public string BarProperty { get; set; }
    }
  8. Install Utf8Json via NuGet

    master

    You can install the core library via NuGet. It supports .NET Framework 4.5 and .NET Standard 2.0.

    There are also official extension packages available for specific use cases:

    • Utf8Json.ImmutableCollection: Support for immutable collections.
    • Utf8Json.UnityShims: Support for Unity.
    • Utf8Json.AspNetCoreMvcFormatter: Binding for ASP.NET Core MVC.
    Install-Package Utf8Json
    Install-Package Utf8Json.ImmutableCollection
    Install-Package Utf8Json.UnityShims
    Install-Package Utf8Json.AspNetCoreMvcFormatter
  9. Configure Utf8Json for Unity (AOT/IL2CPP)

    master

    In Unity, Utf8Json includes a UnityResolver in the StandardResolver to support Unity-specific types like Vector2, Vector3, Quaternion, etc.

    Because Unity's IL2CPP environment is an AOT (Ahead-of-Time) environment, the default runtime IL generation will not work. You must use the Utf8Json.UniversalCodeGenerator.exe to perform pre-code generation.

  10. Integrate Utf8Json with ASP.NET Core MVC

    master

    Use the Utf8Json.AspNetCoreMvcFormatter package to integrate with ASP.NET Core. You can clear existing formatters and add JsonOutputFormatter and JsonInputFormatter to the MVC options. You can also pass a custom IJsonFormatterResolver to the JsonOutputFormatter.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().AddMvcOptions(option => {
            option.OutputFormatters.Clear();
            // can pass IJsonFormatterResolver for customize.
            option.OutputFormatters.Add(new JsonOutputFormatter(StandardResolver.Default));
            option.InputFormatters.Clear();
            option.InputFormatters.Add(new JsonInputFormatter());
        });
    }
  11. Deserialize immutable objects using constructors

    master

    Utf8Json supports deserializing immutable objects (like structs with readonly fields) by matching JSON property names to constructor argument names (case-insensitive).

    If automatic matching fails, you can explicitly specify which constructor to use for deserialization by applying the [SerializationConstructor] attribute to the desired constructor.

    public class CustomPoint
    {
        public readonly int X;
        public readonly int Y;
    
        public CustomPoint(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    
    // used this constructor.
        [SerializationConstructor]
        public CustomPoint(int x)
        {
            this.X = x;
        }
    }
  12. Register custom formatters and resolvers globally

    master

    Use CompositeResolver.RegisterAndSetAsDefault to define a global serialization strategy. This allows you to combine custom formatters, specific enum behaviors, and standard naming conventions into a single resolver used by the default JsonSerializer.

    Example of setting up a global resolver with custom DateTime formatting and SnakeCase naming:

    // use global-singleton CompositeResolver.
    // This method initialize CompositeResolver and set to default JsonSerializer
    CompositeResolver.RegisterAndSetAsDefault(new IJsonFormatter[] {
        // add custome formatters, use other DateTime format.
        // if target type is struct, requires add nullable formatter too(use NullableXxxFormatter or StaticNullableFormatter(innerFormatter))
        new DateTimeFormatter("yyyy-MM-dd HH:mm:ss"),
        new NullableDateTimeFormatter("yyyy-MM-dd HH:mm:ss")
    }, new[] {
        // resolver custom types first
        ImmutableCollectionResolver.Instance,
        EnumResolver.UnderlyingValue,
    
    // finaly choose standard resolver
        StandardResolver.AllowPrivateExcludeNullSnakeCase
    });