using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace Hydra.Backend.Utils; /// /// A base class used for PATCH requests which stores information on whether a key is explicitly set to null or not passed at all. /// public abstract class PatchRequest { private readonly HashSet _properties = []; public bool HasProperty(string propertyName) => _properties.Contains(propertyName); public void SetHasProperty(string propertyName) => _properties.Add(propertyName); } /// /// A custom contract resolver to reduce the boilerplate needed to use . /// Based on this StackOverflow answer: https://stackoverflow.com/a/58748036 /// public class PatchRequestContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var prop = base.CreateProperty(member, memberSerialization); prop.SetIsSpecified += (o, _) => { if (o is not PatchRequest patchRequest) return; patchRequest.SetHasProperty(prop.UnderlyingName!); }; return prop; } }