Nic*_*ick 35 c# json datacontract datamember json.net
我们在使用Microsoft JSON序列化程序和JSON.NET的MVC3项目中遇到了这种情况.
每个人都知道DateTime在Microsoft的序列化程序中基本上被打破了,所以我们切换到JSON.NET来避免这个问题.这很好用,除了我们尝试序列化的一些类是具有DataContract/DataMember属性的POCO.它们在多个位置引用的程序集中定义.此外,它们还具有一些其他显示属性,这些属性未标记为DataMembers以提高效率.例如,客户
[DataContract]
public class Customer
{
[DataMember]
public string FirstName { get; set;}
[DataMember]
public string LastName { get; set;}
public string FullName
{
get
{ return FirstName + " " + LastName; }
}
}
Run Code Online (Sandbox Code Playgroud)
当这个客户通过WCF传递时,客户端可以引用该程序集并使用FullName就好了,但是当使用JSON.NET序列化时,它会看到FullName不是a [DataMember]并且不会序列化它.是否可以选择传递给JSON.NET,告诉它忽略类已[DataContract]应用属性的事实?
注意: 在.NET中使用JavaScriptSerializer可以很好地处理FullName属性,但DateTimes会被破坏.我需要JSON.NET忽略这个类具有DataContract/DataMember属性的事实,并且只是执行标准的公共字段序列化,就像它们不在那里一样.
sel*_*ary 28
只需使用Json.Net的OptOut属性即可.它将优先于DataContract.
[DataContract]
[JsonObject(MemberSerialization.OptOut)]
Run Code Online (Sandbox Code Playgroud)
小智 18
正如Amry所说,你可以使用自己的IContractResolver.
不幸的是,Amry提供的解决方案对我不起作用,下面是我设法开始工作的解决方案:
public class AllPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
//property.HasMemberAttribute = true;
property.Ignored = false;
//property.ShouldSerialize = instance =>
//{
// return true;
//};
return property;
}
}
Run Code Online (Sandbox Code Playgroud)
有几行评论,这些不需要让我的解决方案工作,但你永远不知道!
这与Amry的解决方案具有相同的用法:
var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
ContractResolver = new AllPropertiesResolver()
});
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
Amr*_*mry 14
我遇到了与您所拥有的问题几乎相关的问题,并通过查看Json.NET的代码找到了解决方案.所以它可能不是最好的解决方案,但它对我有用.
要做到这一点,您需要实现自己的IContractResolver.过度简化的实现包括所有参数并忽略所有属性(不仅仅是DataContract其他内置的Json.NET规则,因此您设置的最初应影响成员选择的任何选项现在都被此代码覆盖) :
class AllPropertiesResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
return objectType.GetProperties()
.Where(p => p.GetIndexParameters().Length == 0)
.Cast<MemberInfo>()
.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
这里是代码用法示例:
var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings {
ContractResolver = new AllPropertiesResolver()
});
Run Code Online (Sandbox Code Playgroud)
根据Json.NET文档,[DataMember]如果属性也使用Json.NET特定属性(例如[JsonProperty])注释,则忽略属性.有关详细信息,请参阅序列化属性文档:
Json.NET属性主要使用标准.NET序列化属性,例如,如果属性上存在JsonPropertyAttribute和DataMemberAttribute,并且都自定义名称,则将使用JsonPropertyAttribute中的名称.
该文档仅涵盖name属性,但根据我的经验,该[JsonProperty]属性还完全影响属性所做的设置[DataMember].因此,如果它适用于您的情况,还要将Json.NET属性添加到应忽略[DataMember]注释的属性.
如果要忽略DataContractAttribute所有类型的存在而不必添加其他属性,则自定义合同解析程序是正确的解决方案.但是,从Json.NET 9.0.1开始,Amry的解析器不再有效. Doolali的解析器有效,但它具有序列化所有公共属性的额外副作用,包括标记的那些[JsonIgnore].如果您需要合同解析程序,只能忽略其存在DataContractAttribute但行为类似于默认合同解析程序,则可以使用以下内容:
public class IgnoreDataContractContractResolver : DefaultContractResolver
{
static MemberSerialization RemoveDataContractAttributeMemberSerialization(Type type, MemberSerialization memberSerialization)
{
if (memberSerialization == MemberSerialization.OptIn)
{
type = Nullable.GetUnderlyingType(type) ?? type;
// Json.NET interprets DataContractAttribute as inherited despite the fact it is marked with Inherited = false
// https://json.codeplex.com/discussions/357850
// https://stackoverflow.com/questions/8555089/datacontract-and-inheritance
// https://github.com/JamesNK/Newtonsoft.Json/issues/603
// Thus we need to manually climb the type hierarchy to see if one is present.
var dataContractAttribute = type.BaseTypesAndSelf().Select(t => t.GetCustomAttribute<DataContractAttribute>()).FirstOrDefault(a => a != null);
var jsonObjectAttribute = type.GetCustomAttribute<JsonObjectAttribute>();
if (dataContractAttribute != null && jsonObjectAttribute == null)
memberSerialization = MemberSerialization.OptOut;
}
return memberSerialization;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, RemoveDataContractAttributeMemberSerialization(type, memberSerialization));
return properties;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.MemberSerialization = RemoveDataContractAttributeMemberSerialization(objectType, contract.MemberSerialization);
return contract;
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可能希望缓存合同解析程序以获得最佳性能.
| 归档时间: |
|
| 查看次数: |
23609 次 |
| 最近记录: |