using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace Idoklad.Infrastructure; /// /// Makes iDoklad SDK models serializable. Some SDK converters, attached through /// , only support reading and their WriteJson throws /// , which turns any response carrying such a model into a /// 500. This resolver replaces them with : reading keeps /// using the SDK converter, writing falls back to the standard serialization. Everything else is /// left to . /// public sealed class SdkContractResolver : DefaultContractResolver { /// /// SDK converters that cannot write. Converters that do implement writing (for example /// NullablePropertyJsonConverter) are deliberately not listed here. /// private static readonly HashSet WriteUnsupportedConverterTypeNames = new(StringComparer.Ordinal) { // Attached to DateTime members of the invoice, bank account, cash register and similar models. "IdokladSdk.Serialization.DateTimeConverter", // Attached to the NotificationListGetModel type itself. "IdokladSdk.Serialization.NotificationJsonConverter", }; protected override JsonContract CreateContract(Type objectType) { var contract = base.CreateContract(objectType); contract.Converter = Replace(contract.Converter); return contract; } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); property.Converter = Replace(property.Converter); // Collections carry the member converter as the item converter instead. property.ItemConverter = Replace(property.ItemConverter); return property; } private static JsonConverter? Replace(JsonConverter? converter) { var typeName = converter?.GetType().FullName; return typeName is not null && WriteUnsupportedConverterTypeNames.Contains(typeName) ? new SdkWriteBypassJsonConverter(converter!) : converter; } }