using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public static class SerializationInfoExtensions
static Lazy<Func<SerializationInfo, string, Type, object?>?> GetValueNoThrowFunc = new(
var method = typeof(SerializationInfo).GetMethod("GetValueNoThrow", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, new [] { typeof(string), typeof(Type)});
return (Func<SerializationInfo, string, Type, object?>)Delegate.CreateDelegate(typeof(Func<SerializationInfo, string, Type, object?>), null, method);
public static object? GetValueNoThrow(this SerializationInfo info, string name, Type type)
ArgumentNullException.ThrowIfNull(info);
ArgumentNullException.ThrowIfNull(name);
ArgumentNullException.ThrowIfNull(type);
var func = GetValueNoThrowFunc.Value;
return func(info, name, type);
return info.GetValue(name, type);
catch (SerializationException)
internal sealed class User : ISerializable
private User(SerializationInfo info, StreamingContext context)
Name = (string)info.GetValue(nameof(Name), typeof(string));
Group = (UserGroup)info.GetValueNoThrow(nameof(Group), typeof(UserGroup));
public string Name { get; set; }
public UserGroup Group { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
info.AddValue(nameof(Name), Name);
info.AddValue(nameof(Group), Group);
internal sealed class UserGroup : ISerializable
private UserGroup(SerializationInfo info, StreamingContext context)
Name = (string)info.GetValue(nameof(Name), typeof(string));
DefaultUser = (User)info.GetValueNoThrow(nameof(DefaultUser), typeof(User));
public string Name { get; set; }
public User DefaultUser { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
info.AddValue(nameof(Name), Name);
info.AddValue(nameof(DefaultUser), DefaultUser);
public static void Test()
var user = new DataClasses.User { Name = "User" };
var group = new DataClasses.UserGroup { Name = "Group", DefaultUser = user };
var settings = new JsonSerializerSettings
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
var json = JsonConvert.SerializeObject(user, settings);
var userRestored = JsonConvert.DeserializeObject<DataClasses.User>(json);
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: ");