我想知道是否有人能指出我正确的方向来轻松解决以下问题:
假设我的.NET代码中有一个Player类,如下所示:
public class Player
{
public int Id { get; set; }
public string Name { get; set; }
public long Score { get; set; }
}
我需要将此类序列化为JSON字符串(使用JSON.NET)并在POST到Web服务时使用它。但是,问题在于某些服务的端点明确禁止在JSON字符串中出现某些成员。例如,“post score”端点将允许所有3个成员包含在字符串中,而“register player”端点仅允许Id和Name存在(否则,将错误请求返回给客户端) )。现在我知道我可以创建两个不同的类(例如Player和CompetitivePlayer),每个类都包含所需的(子)成员集,但是出于实际目的,让我们假设我不能这样做或者想要避免这种情况(我的实际数据对象)比这里给出的Player类更复杂,只是作为例子。)
所以我真正想要的是在运行时告诉JSON序列化程序,只有某个对象的某些成员必须在情境X中被序列化,而在情况Y中,整个不同的子集将被序列化。起初我认为实现我自己的ContractResolver会有所帮助,但事实证明,每个对象的类型只调用一次,而不是每个对象本身在序列化时调用。现在,我能想到的唯一解决方案是继承JSONSerializer并让它使用JSONWriter忽略其名称包含在作为参数给出的字符串列表中的属性 - 也许 - 虽然我不太确定这个计划是否可行。对于我想要实现的目标,是否有更简单的解决方案?
答案 0 :(得分:3)
好的,在查看了JSON.NET源代码之后,我找到了阻止我自定义序列化这些属性的确切位置:CamelCasePropertyNamesContractResolver
类。
在编写原始问题之前,我尝试在IContractResolver
部分实现此处所述的自定义序列化。但是,我没有直接从DefaultContractResolver
继承,而是使用CamelCasePropertyNamesContractResolver
(我在这里需要骆驼案例),在查看其代码后,设置了一个"共享缓存"由于性能原因(我愿意在这种情况下牺牲),因此阻止某些方法被调用的标志。因此,CreateProperties()
每个对象类型只调用一次,而不是每次我的对象都需要序列化。所以现在我的合同解析器类看起来像这样:
class OptionalPropertiesContractResolver : DefaultContractResolver
{
//only the properties whose names are included in this list will be serialized
IEnumerable<string> _includedProperties;
public OptionalPropertiesContractResolver(IEnumerable<string> includedProperties)
{
_includedProperties = includedProperties;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return (from prop in base.CreateProperties(type, memberSerialization)
where _includedProperties.Contains(prop.PropertyName)
select prop).ToList();
}
protected override string ResolvePropertyName(string propertyName)
{
// lower case the first letter of the passed in name
return ToCamelCase(propertyName);
}
static string ToCamelCase(string s)
{
//camel case implementation
}
}
只是想让别人知道这种特殊情况,以防万一遇到它。
答案 1 :(得分:0)
我会创建合约类并使用AutoMapper从Player类映射到它们并根据需要序列化它们。即'PlayerContract','CompetitivePlayerContract'等。
这些类只代表您服务的合同并不重要。