Is there any way to take the settings out of a JsonSerializer
class and reimplement them in a new JsonSerializer
?
There doesn't seem to be any methods to do anything like that. The best I found was a private method to be called through reflection, ApplySerializerSettings
.
I'm trying to take the serializer from the WriteJson
method and copy it into a new serializer, tweaking it a bit. Specifically I want to replace the ContractResolver
.
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
On iOS 7 and later and macOS 10.9 and later, JSONSerialization is thread safe.
JsonSerializerOptions.NumberHandling Property (System.Text.Json) Gets or sets an object that specifies how number types should be handled when serializing or deserializing.
SerializeObject Method (Object, Type, JsonSerializerSettings) Serializes the specified object to a JSON string using a type, formatting and JsonSerializerSettings. Namespace: Newtonsoft.Json.
Seems like the best way is to just copy all the settings into a new object. There are a ton of them, so here's a nice extension method to work with (as of 8.0.3).
public static class JsonSerializerExtensions
{
public static JsonSerializer DeepCopy(this JsonSerializer serializer)
{
var copiedSerializer = new JsonSerializer
{
Context = serializer.Context,
Culture = serializer.Culture,
ContractResolver = serializer.ContractResolver,
ConstructorHandling = serializer.ConstructorHandling,
CheckAdditionalContent = serializer.CheckAdditionalContent,
DateFormatHandling = serializer.DateFormatHandling,
DateFormatString = serializer.DateFormatString,
DateParseHandling = serializer.DateParseHandling,
DateTimeZoneHandling = serializer.DateTimeZoneHandling,
DefaultValueHandling = serializer.DefaultValueHandling,
EqualityComparer = serializer.EqualityComparer,
FloatFormatHandling = serializer.FloatFormatHandling,
Formatting = serializer.Formatting,
FloatParseHandling = serializer.FloatParseHandling,
MaxDepth = serializer.MaxDepth,
MetadataPropertyHandling = serializer.MetadataPropertyHandling,
MissingMemberHandling = serializer.MissingMemberHandling,
NullValueHandling = serializer.NullValueHandling,
ObjectCreationHandling = serializer.ObjectCreationHandling,
PreserveReferencesHandling = serializer.PreserveReferencesHandling,
ReferenceResolver = serializer.ReferenceResolver,
ReferenceLoopHandling = serializer.ReferenceLoopHandling,
StringEscapeHandling = serializer.StringEscapeHandling,
TraceWriter = serializer.TraceWriter,
TypeNameHandling = serializer.TypeNameHandling,
SerializationBinder = serializer.SerializationBinder,
TypeNameAssemblyFormatHandling = serializer.TypeNameAssemblyFormatHandling
};
foreach (var converter in serializer.Converters)
{
copiedSerializer.Converters.Add(converter);
}
return copiedSerializer;
}
}
It's ugly, but at least you only have to write it once. Be slightly careful, as the properties themselves are not deep copied.
Answer below is flaky depending on your implementation, especially when it comes to resolving a contract. Keeping it in just in case it helps someone.
So, I can't quite copy the settings, but I found a good work around that might want to be considered. You can simply set the properties you want to change, in a locked context, and then reset them afterward.
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var thing = value as IThing;
if (thing == null)
throw new ArgumentException($"Writing Json failed because " +
"value was not a 'Thing' of type, {typeof(IThing).FullName}");
JObject jsonThing;
//If your solution is multithreaded,
//and is using a shared serializer (which you probably are),
//you should lock the serializer so that it doesn't accidentally use
//the "CustomObjectResolver"
lock (serializer)
{
//Hold the original value(s) to reset later
var originalContractResolver = serializer.ContractResolver;
//Set custom value(s)
serializer.ContractResolver = new CustomObjectResolver();
//Serialization with custom properties
jsonThing = JObject.FromObject(value, serializer);
//Reset original value(s)
serializer.ContractResolver = originalContractResolver;
}
//Finish serializing and write to writer.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With