微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

rest – 在ASP.NET Core中实现“JSON Merge Patch” – 最好的方法是区分null和未定义的属性

我想创建和端点符合“ JSON Merge Patch” https://tools.ietf.org/html/rfc7396

请不要将它与“JavaScript Object Notation(JSON)Patch”混淆
https://tools.ietf.org/html/rfc6902

但是,我在区分请求中的两种情况时遇到了一些问题:

>删除属性值,此处删除电子邮件值:

{
    surname: "Kowalski"
    email: null
}

>不包括属性,因为客户端根本不想更新它,此处不包含电子邮件,因为它不应更新:

{
    surname: "Kowalski"
}

出现问题的原因是在模型绑定后的两种情况下,电子邮件的值都为null.

您是否有建议如何实施?

解决方法

您需要3种不同的电子邮件状态:

>更新的填充值(例如[email protected])
>如果要删除电子邮件,则为null值
>如果不接触电子邮件,则缺少值.

所以问题实际上是如何在模型的字符串属性中表达这3种状态.您不能仅使用原始字符串属性执行此操作,因为空值和缺失值将如您正确描述的那样发生冲突.
解决方案是使用一些标志来指示值是否在请求中提供.您可以将此标志作为模型中的另一个属性,或者在字符串上创建一个简单的包装器,非常类似于Nullable< T>类.
我建议创建简单的通用OptionalValue< T>类:

public class OptionalValue<T>
{
    private T value;
    public T Value
    {
        get => value;

        set
        {
            HasValue = true;
            this.value = value;
        }
    }

    public bool HasValue { get; set; }
}

然后你需要自定义JsonConverter,它可以将通常的json值反序列化为OptionalValue< T>:

class OptionalValueConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(OptionalValue<T>);
    }

    public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
    {
        return new OptionalValue<T>
        {
            Value = (T) reader.Value,};
    }

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

你的模型看起来像这样:

public class SomeModel
{
    public string Surname { get; set; }

    [JsonConverter(typeof(OptionalValueConverter<string>))]
    public OptionalValue<string> Email { get; set; } = new OptionalValue<string>();
}

请注意,您使用空OptionalValue< string>()分配电子邮件.如果输入json不包含电子邮件值而不是Email属性,则将其与HasValue设置为false的OptionalValue保持一致.
如果输入json包含一些电子邮件,甚至是null,则OptionalValueConverter将创建OptionalValue的实例,并将HasValue设置为true.

现在,在控制器操作中,您可以确定电子邮件的3种状态:

[HttpPatch]
public void Patch([FromBody]SomeModel data)
{
    if (data.Email.HasValue)
    {
        //  Email presents in Json
        if (data.Email.Value == null)
        {
            //  Email should be removed
        }
        else
        {
            //  Email should be updated
        }
    }
    else
    {
        //  Email does not present in Json and should not be affected
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐