using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Schema;
public class SelectedPrivateSettersContractResolver : DefaultContractResolver
HashSet<Type> privateSetterTypes { get; } = new ();
public SelectedPrivateSettersContractResolver(params Type [] types) : this((IEnumerable<Type>)types) { }
public SelectedPrivateSettersContractResolver(IEnumerable<Type> types) =>
privateSetterTypes.UnionWith(types ?? throw new ArgumentNullException());
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
var prop = base.CreateProperty(member, memberSerialization);
if (!prop.Ignored && prop.Readable && !prop.Writable)
if (privateSetterTypes.Contains(prop.DeclaringType))
if (member is PropertyInfo property)
prop.Writable = property.GetSetMethod(true) != null;
public static void Test()
public static void TestSchema()
var schemaJson = GetJsonSchema();
var schema = JSchema.Parse(schemaJson);
var model = JObject.Parse(GetJson());
var valid = model.IsValid(schema, out IList<Newtonsoft.Json.Schema.ValidationError> errors);
var settings = new JsonSerializerSettings
ContractResolver = new SelectedPrivateSettersContractResolver(typeof(ValidationError)),
var resultStr = JsonConvert.SerializeObject(errors, Formatting.Indented, settings);
var ReSerializedResult = JsonConvert.DeserializeObject<List<ValidationError>>(resultStr, settings);
var resultStr2 = JsonConvert.SerializeObject(ReSerializedResult, Formatting.Indented, settings);
Console.WriteLine(resultStr);
Console.WriteLine(resultStr2);
Assert.IsTrue(errors.Select(e => e.SchemaId).SequenceEqual(ReSerializedResult.Select(e => e.SchemaId)));
var inModel = new Model("my value");
var settings = new JsonSerializerSettings
ContractResolver = new SelectedPrivateSettersContractResolver(typeof(Model)),
var json = JsonConvert.SerializeObject(inModel, settings);
var newModel1 = JsonConvert.DeserializeObject<Model>(json);
Assert.AreNotEqual(inModel.Value, newModel1.Value);
var newModel2 = JsonConvert.DeserializeObject<Model>(json, settings);
Assert.AreEqual(inModel.Value, newModel2.Value);
static string GetJsonSchema()
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""description"": ""article metadata for descrepancy checks"",
""description"": ""authors details"",
""description"": ""32 digit unique id to identify author"",
""sequence_id"": ""Au1"",
""guid"": ""00208406-c337-4f58-9245-9455d8852a00"",
""affiliation_id"": ""Aff1"",
""family_name"": ""Hole""
""sequence_id"": ""Au2"",
""guid"": ""32b8a598-2fb5-42f1-ad0e-94ce2fc00a8f"",
""affiliation_id"": ""Aff2"",
""given_name"": ""Anurag""
public Model(string value) => this.Value = value;
public string Value { get; private set; }
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Json.NET Schema version: " + typeof(Newtonsoft.Json.Schema.JSchema).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];