Jef*_*f G 11 c# serialization json json.net
我有以下类结构:
[JsonObject]
public class Polygon : IEnumerable<Point>
{
public List<Point> Vertices { get; set; }
public AxisAlignedRectangle Envelope { get; set; }
}
public class AxisAlignedRectangle : Polygon {
public double Left { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)
我正在序列化这个Polygon类,但是当我这样做时,我得到一个JsonSerializationException消息"为属性'Envelope'检测到自我引用循环',类型为'MyNamespace.AxisAlignedRectangle'." 如果我将[JsonObject(IsReference = true)](如此处所述)添加到AxisAlignedRectangle,代码运行正常,但我在AxisAlignedRectangle的每个实例中获得一个自动分配的$ id字段,并在重新引用该实例时获得$ ref字段.例如,当我序列化多边形时,我得到:
{
Vertices: [ ... ],
Envelope: {
$id: '1',
Left: -5,
...
Vertices: [ ... ],
Envelope: {
$ref: '1'
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望在序列化AxisAlignedRectangle时完全删除Polygon属性.我尝试DataContractAttribute在AxisAlignedRectangle类中添加一个(以及适当的DataMemberAttribute属性),但Polygon的所有属性仍然被序列化.这是意料之外的,因为Json.NET文档中有一个示例表明这种方法应该有效.
当被序列化的类型是AxisAlignedRectangle时,有没有人知道从生成的Json.NET序列化中显式删除(最重要的)Envelope属性的方法?谢谢.
yon*_*sha 16
最简单的方法是简单地用AxisAlignedRectangle对象进行装饰[JsonObject(MemberSerialization.OptIn)].
在一个句子中,它将仅序列化用[JsonProperty]属性修饰的属性.您可以在这里阅读更多内容:MemberSerialization Enumeration.
另一个选择是使用JsonIgnoreAttribute类装饰Polygon属性.
我遇到了同样的事情。JsonIgnoreAttribute如果某个属性应该始终被 ingored 并且您可以访问包含该属性的类,这是一个很好的解决方案。但是如果你想确定哪些属性应该在序列化时序列化,你可以使用 ContractResolver。
这是一个实现,它允许您从最派生的类开始序列化属性,并在给定的基类处停止。就我而言,我想序列化自定义 CMS (EPiServer) 页面类型的属性,但不想序列化页面类的所有内置属性。
public class DerivedClassContractResolver : DefaultContractResolver
{
private Type _stopAtBaseType;
public DerivedClassContractResolver(Type stopAtBaseType)
{
_stopAtBaseType = stopAtBaseType;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
Type originalType = GetOriginalType(type);
IList<JsonProperty> defaultProperties = base.CreateProperties(type, memberSerialization);
List<string> includedProperties = Utilities.GetPropertyNames(originalType, _stopAtBaseType);
return defaultProperties.Where(p => includedProperties.Contains(p.PropertyName)).ToList();
}
private Type GetOriginalType(Type type)
{
Type originalType = type;
//If the type is a dynamic proxy, get the base type
if (typeof(Castle.DynamicProxy.IProxyTargetAccessor).IsAssignableFrom(type))
originalType = type.BaseType ?? type;
return originalType;
}
}
public class Utilities
{
/// <summary>
/// Gets a list of all public instance properties of a given class type
/// excluding those belonging to or inherited by the given base type.
/// </summary>
/// <param name="type">The Type to get property names for</param>
/// <param name="stopAtType">A base type inherited by type whose properties should not be included.</param>
/// <returns></returns>
public static List<string> GetPropertyNames(Type type, Type stopAtBaseType)
{
List<string> propertyNames = new List<string>();
if (type == null || type == stopAtBaseType) return propertyNames;
Type currentType = type;
do
{
PropertyInfo[] properties = currentType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
foreach (PropertyInfo property in properties)
if (!propertyNames.Contains(property.Name))
propertyNames.Add(property.Name);
currentType = currentType.BaseType;
} while (currentType != null && currentType != stopAtBaseType);
return propertyNames;
}
}
Run Code Online (Sandbox Code Playgroud)
这让我做这样的事情:
JsonConvert.SerializeObject(page, new JsonSerializerSettings()
{
ContractResolver = new DerivedClassContractResolver(typeof(EPiServer.Core.PageData))
}));
Run Code Online (Sandbox Code Playgroud)
获取我在自己的类上定义的属性,而无需获取从 EPiServer.Core.PageData 继承的大量属性。注意:GetOriginalType()如果您不使用Castle DynamicProxy项目(EPiServer CMS使用),则不需要代码。
您可以通过如下定义类来使用条件属性序列化:
[JsonObject]
public class Polygon : IEnumerable<Point>
{
public List<Point> Vertices { get; set; }
public AxisAlignedRectangle Envelope { get; set; }
public virtual bool ShouldSerializeEnvelope()
{
return true;
}
}
public class AxisAlignedRectangle : Polygon
{
public double Left { get; set; }
...
public override bool ShouldSerializeEnvelope()
{
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经在以下位置发布了完整的解决方案:https : //github.com/thiagoavelino/VisualStudio_C/blob/master/VisualStudio_C/StackOverFlow/ParsingJason/EnvelopePolygonProblem.cs
| 归档时间: |
|
| 查看次数: |
9222 次 |
| 最近记录: |