using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public static class StreamingContextExtensions
public static StreamingContext AddTypeData(this StreamingContext context, Type type, object? data)
IStreamingContextTypeDataDictionary dictionary;
if (context.Context == null)
dictionary = new StreamingContextTypeDataDictionary();
else if (context.Context is IStreamingContextTypeDataDictionary d)
throw new InvalidOperationException(string.Format("context.Context is already populated with {0}", context.Context));
dictionary.AddData(type, data);
return new StreamingContext(context.State, dictionary);
public static bool TryGetTypeData(this StreamingContext context, Type type, out object? data)
IStreamingContextTypeDataDictionary? dictionary = context.Context as IStreamingContextTypeDataDictionary;
return dictionary.TryGetData(type, out data);
public interface IStreamingContextTypeDataDictionary
public void AddData(Type type, object? data);
public bool TryGetData(Type type, out object? data);
class StreamingContextTypeDataDictionary : IStreamingContextTypeDataDictionary
readonly Dictionary<Type, object?> dictionary = new ();
public void AddData(Type type, object? data) => dictionary.Add(type, data);
public bool TryGetData(Type type, out object? data) => dictionary.TryGetValue(type, out data);
[JsonConverter(typeof(MyJsonConverter))]
public string Property { get; set; }
public class MyJsonConverter : JsonConverter
public override bool CanConvert(Type objectType) => objectType == typeof(string);
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
var _parameter = serializer.Context.TryGetTypeData(typeof(MyJsonConverter), out var s) ? (string?)s : "";
return _parameter + (string?)JToken.Load(reader);
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) =>
writer.WriteValue((string)value!);
public static void Test()
var originalContract = new Contract { Property = "hello" };
var json = JsonConvert.SerializeObject(originalContract);
var _parameter = "my runtime parameter: ";
var settings = new JsonSerializerSettings
Context = new StreamingContext(StreamingContextStates.All)
.AddTypeData(typeof(MyJsonConverter), _parameter),
var contract = JsonConvert.DeserializeObject<Contract>(json, settings);
Console.WriteLine("Round-tripped {0}:", contract);
Console.WriteLine(JsonConvert.SerializeObject(contract, settings));
Assert.AreEqual(_parameter + originalContract.Property, contract?.Property);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Namespace, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");