C# JSON.NET部分更新Rest API客户端

C# JSON.NET部分更新Rest API客户端,c#,.net,json,rest,json.net,C#,.net,Json,Rest,Json.net,我正在使用JSON.NET为REST API构建一个C#/.NET 4.5客户端。API支持部分更新;因此,更新时json中是否存在属性具有意义。如果属性在json中,服务器将相应地设置值;未传递该属性,服务器将不会更新该属性。这也适用于空值。我为每种型号都开设了.NET课程;每个JSON属性都有属性(相当标准) 例如,假设服务器上已经存在此帐户对象(名称、注释): { 'name':'craig', 'notes:'these are notes' } var account =

我正在使用JSON.NET为REST API构建一个C#/.NET 4.5客户端。API支持部分更新;因此,更新时json中是否存在属性具有意义。如果属性在json中,服务器将相应地设置值;未传递该属性,服务器将不会更新该属性。这也适用于空值。我为每种型号都开设了.NET课程;每个JSON属性都有属性(相当标准)

例如,假设服务器上已经存在此帐户对象(名称、注释):

{
   'name':'craig',
   'notes:'these are notes'
}
var account = api.GetAccount();
account.Name = "bob";
account.Notes = null;
api.UpdateAccount(account);

{
   'name':'bob',
   'notes':null
}
如果我传入此json进行更新,它将更新名称,但会将注释设置为“There are notes”:

var account = api.GetAccount();
account.Name = "bob";
api.UpdateAccount(account);

{
   'name':'bob'
}
如果我传入此json进行更新,它将在服务器上将名称和注释设置为null:

{
   'name':'craig',
   'notes:'these are notes'
}
var account = api.GetAccount();
account.Name = "bob";
account.Notes = null;
api.UpdateAccount(account);

{
   'name':'bob',
   'notes':null
}
到目前为止一切都很好

我的问题是如何让JSON.NET很好地处理这个问题。JSON.NET允许控制NullValueHandling,它基本上表示是否应该序列化null值。然而,在这种情况下,这是不够的。我需要能够确定调用代码是否显式地将值设置为null。有没有推荐的处理方法

我尝试使用模型内部的字典来存储要通过JSON序列化的属性。这允许我通过字典中的键来判断属性是否被设置为任何值(包括null)。我发现这种方法有一些困难,最后我重写了许多JSON.NET标准的代码(类型序列化、泛型、空值、枚举…)

注意:我意识到上面的例子有点做作。实际上,从服务器返回的account对象将同时填充name和notes,并且当更新发生时,它将同时发送回这两个对象

这适用的另一种情况是在创建对象和处理服务器生成的默认值期间。例如,假设服务器在创建帐户时将帐户的注释默认为“在此处放置注释”。如果我传入带有null值的Notes属性,服务器将认为客户端希望将其设置为null。但实际情况是,客户机并没有试图将Notes设置为null,在这种情况下,客户机希望设置默认值

var account = new Account();
account.Name = "bob";
api.CreateAccount(account);

{
   'name':'bob',
   'notes':null
}

我一直对JSON.NET印象深刻

这就是我的结局。我使用了ContractResolver、ShouldSerialize谓词和NullValueHandling属性的组合。这是非常有用的。属性存储在基类ApiModel中的字典中;这段代码很简单

账户模式

[JsonProperty("name")]
public string Name
{
    get { return this.GetAttributeValue<string>("name"); }
    set { this.SetAttributeValue<string>("name", value); }
}

我自己也遇到了类似的问题。编写了一个类来简化这个过程。也在NuGet上列出