Quartz.Serialization.Newtonsoft 4.0.0-alpha.1

Prefix Reserved
This is a prerelease version of Quartz.Serialization.Newtonsoft.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Quartz.Serialization.Newtonsoft --version 4.0.0-alpha.1
                    
NuGet\Install-Package Quartz.Serialization.Newtonsoft -Version 4.0.0-alpha.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Quartz.Serialization.Newtonsoft" Version="4.0.0-alpha.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Quartz.Serialization.Newtonsoft" Version="4.0.0-alpha.1" />
                    
Directory.Packages.props
<PackageReference Include="Quartz.Serialization.Newtonsoft" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Quartz.Serialization.Newtonsoft --version 4.0.0-alpha.1
                    
#r "nuget: Quartz.Serialization.Newtonsoft, 4.0.0-alpha.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Quartz.Serialization.Newtonsoft@4.0.0-alpha.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Quartz.Serialization.Newtonsoft&version=4.0.0-alpha.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Quartz.Serialization.Newtonsoft&version=4.0.0-alpha.1&prerelease
                    
Install as a Cake Tool

title: JSON Serialization

::: tip JSON is the recommended format for data a job store persists. Consider also setting StoreJobDataAsStrings, which keeps job data out of the serializer altogether by restricting it to strings. :::

::: tip System.Text.Json serialization is built into the Quartz package and is the default; see Serialization (System.Text.Json). :::

JSON.NET

Quartz.Serialization.Newtonsoft provides JSON serialization support for job stores using Json.NET to handle the actual serialization process.

Installation

You need to add NuGet package reference to your project which uses Quartz.

dotnet add package Quartz.Serialization.Newtonsoft

Configuring

Configuring the store

builder.Services.AddQuartz(q => q.UsePersistentStore(store =>
{
    store.UseSqlServer(connectionString);

    // it's generally recommended to stick with
    // string property keys and values when serializing
    store.Configure(options => options.StoreJobDataAsStrings = true);

    store.UseNewtonsoftJsonSerializer();
}));

Without a host, the same calls hang off QuartzSchedulerBuilder:

await using StandaloneSchedulerFactory schedulerFactory = QuartzSchedulerBuilder.Create()
    .UsePersistentStore(store =>
    {
        store.UseGenericDatabase("MyProvider", "my connection string");
        store.Configure(options => options.StoreJobDataAsStrings = true);
        store.UseNewtonsoftJsonSerializer();
    })
    .Build();

Build() returns a StandaloneSchedulerFactory, which owns the container it built: dispose it — with await using, as above — and the scheduler shuts down with it.

Classic property-based configuration

The flat keys 3.x used still work, and mean the same thing:

NameValueCollection properties = new()
{
    ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.LocalTransactionJobStore, Quartz",
    ["quartz.serializer.type"] = "newtonsoft"
};

await using StandaloneSchedulerFactory schedulerFactory = QuartzSchedulerBuilder.Create()
    .UseProperties(properties)
    .Build();

UseGenericDatabase is the right method only for a database Quartz has no specific support for; use UseSqlServer, UsePostgres and the rest otherwise. If Quartz ships no description of your ADO.NET driver either, describe it in the same call — see the configuration reference.

Migrating from binary serialization

Quartz 4 no longer ships the BinaryObjectSerializer: the underlying BinaryFormatter has been removed from modern .NET and throws on .NET 9 and later. If you still have binary-serialized data in your database you need to migrate it to JSON.

The recommended path is to perform the migration while you are still on Quartz 3.x, which still includes BinaryObjectSerializer - see the Quartz 3.x version of this page for a ready-made hybrid serializer. Either let the system migrate gradually as it runs, or write a small program that loads and writes back every serialized asset in the database.

If you must read legacy binary data after upgrading to Quartz 4 on .NET 9 or later, you can re-enable BinaryFormatter with Microsoft's unsupported compatibility package. Because the package does not change BinaryFormatter's type identity, only your application project needs it - Quartz itself does not reference it:

<PropertyGroup>
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
<ItemGroup>
  
  <PackageReference Include="System.Runtime.Serialization.Formatters" Version="10.0.0" />
</ItemGroup>

The package restores a working - but still unsafe - BinaryFormatter, so read the Microsoft guidance before relying on it and remove it once the migration is complete. The Quartz types a blob can be made of - the job data maps, the keys that can sit in them as values, the calendars and the trigger classes - keep their [Serializable] / ISerializable support, so the hybrid serializer below can read the old binary payloads and write everything back as JSON. Types that could never be part of a blob lost those attributes in 4.0; see the migration guide for the full list.

One column is the exception: BLOB_TRIGGERS.BLOB_DATA holds whole trigger objects, and BinaryFormatter records private base-class fields under the base class's name - which 4.0 renamed (AbstractTrigger is TriggerBase) and whose field set 4.0 extended. Migrate binary blob triggers while still on 3.x; the hybrid serializer on 4.x is for the job data map, key and calendar payloads.

Example hybrid serializer

using System.Runtime.Serialization.Formatters.Binary;

using Newtonsoft.Json;

using Quartz.Impl;
using Quartz.Extensibility;

namespace Quartz;

public sealed class MigratorSerializer : IObjectSerializer
{
    // you might need custom configuration, see sections about customizing in documentation
    private readonly NewtonsoftJsonObjectSerializer jsonSerializer = new();

    public T Deserialize<T>(byte[] data) where T : class
    {
        try
        {
            // Attempt to deserialize data as JSON
            return jsonSerializer.Deserialize<T>(data)!;
        }
        catch (JsonReaderException)
        {
            // The data was not JSON, so fall back to the legacy binary format. This branch needs
            // the System.Runtime.Serialization.Formatters compatibility package and
            // EnableUnsafeBinaryFormatterSerialization to be set in the application project.
            using var stream = new MemoryStream(data);
#pragma warning disable SYSLIB0011
            var binaryData = (T) new BinaryFormatter().Deserialize(stream);
#pragma warning restore SYSLIB0011
            if (binaryData is JobDataMap jobDataMap)
            {
                // make sure we mark the map as dirty so it will be serialized as JSON next time
                jobDataMap[SchedulerConstants.ForceJobDataMapDirty] = "true";
            }
            return binaryData;
        }
    }

    public byte[] Serialize<T>(T obj) where T : class => jsonSerializer.Serialize(obj);
}

Customizing JSON.NET

If you need to customize JSON.NET settings, you need to inherit custom implementation and override CreateSerializerSettings.

class CustomJsonSerializer : NewtonsoftJsonObjectSerializer
{
    protected override JsonSerializerSettings CreateSerializerSettings()
    {
        var settings = base.CreateSerializerSettings();
        settings.Converters.Add(new MyCustomConverter());
        return settings;
    }
}

And then configure it to use

store.UseSerializer<CustomJsonSerializer>();

or, as a flat property key:

quartz.serializer.type = MyProject.CustomJsonSerializer, MyProject

Customizing calendar serialization

If you have implemented a custom calendar, you need to implement a ICalendarSerializer for it. There's a convenience base class CalendarSerializer that you can use the get strongly-typed experience.

Custom calendar and serializer

[Serializable]
class CustomCalendar : BaseCalendar
{
    public CustomCalendar()
    {
    }

    // binary serialization support
    protected CustomCalendar(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        SomeCustomProperty = info?.GetBoolean("SomeCustomProperty") ?? true;
    }

    public bool SomeCustomProperty { get; set; } = true;

    // binary serialization support
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info?.AddValue("SomeCustomProperty", SomeCustomProperty);
    }
}

// JSON serialization support
class CustomCalendarSerializer : CalendarSerializer<CustomCalendar>
{
    protected override CustomCalendar Create(JObject source)
    {
        return new CustomCalendar();
    }

    protected override void SerializeFields(JsonWriter writer, CustomCalendar calendar)
    {
        writer.WritePropertyName("SomeCustomProperty");
        writer.WriteValue(calendar.SomeCustomProperty);
    }

    protected override void DeserializeFields(CustomCalendar calendar, JObject source)
    {
        calendar.SomeCustomProperty = source["SomeCustomProperty"]!.Value<bool>();
    }
}

A serializer can optionally override CalendarTypeName to give the calendar a serializer-neutral name — the same discriminator the System.Text.Json package would use for it. The registry then finds the serializer under that name as well as under the calendar's assembly-qualified type name, so a payload written by either package resolves. Leave it unset and the serializer answers only to the assembly-qualified name, which is what payloads written by 3.x carry.

Configuring custom calendar serializer

builder.Services.AddQuartz(q => q.UsePersistentStore(store =>
{
    store.UseNewtonsoftJsonSerializer(json =>
    {
        json.AddCalendarSerializer<CustomCalendar>(new CustomCalendarSerializer());
    });
}));

::: warning Changed in 4.0 NewtonsoftJsonObjectSerializer.AddCalendarSerializer and AddTriggerSerializer were static in 3.x, so every scheduler in the process shared one set of custom serializers and registration order silently decided which one won. They have been removed. Register through the UseNewtonsoftJsonSerializer callback as above: what the callback registers belongs to that scheduler alone, so two schedulers in one container can serialize different custom types. :::

If you build a serializer yourself rather than through the store builder, hand it a NewtonsoftJsonSerializerRegistry. A new registry already knows every built-in trigger and calendar type, so registering a custom one adds to that set:

NewtonsoftJsonSerializerRegistry registry = new NewtonsoftJsonSerializerRegistry()
    .AddCalendarSerializer<CustomCalendar>(new CustomCalendarSerializer())
    .AddTriggerSerializer<CustomTrigger>(new CustomTriggerSerializer());

NewtonsoftJsonObjectSerializer serializer = new(registry);
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Quartz.Serialization.Newtonsoft:

Package Downloads
Quartz.Serialization.Json

Renamed to Quartz.Serialization.Newtonsoft in 4.0. This package is empty and exists only so a grouped dependency update can move to 4.x - reference Quartz.Serialization.Newtonsoft instead, and see the migration guide.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.1.0 2,094 9/13/2026
4.0.1 1,708 9/8/2026
4.0.0 584 9/3/2026
4.0.0-rc.2 67 9/3/2026
4.0.0-rc.1 69 9/3/2026
4.0.0-beta.1 69 9/2/2026
4.0.0-alpha.5 70 8/31/2026
4.0.0-alpha.4 66 8/31/2026
4.0.0-alpha.3 67 8/27/2026
4.0.0-alpha.2 76 8/25/2026
4.0.0-alpha.1 86 8/22/2026