【问题标题】:Exclude executable property from JSON serialization从 JSON 序列化中排除可执行属性
【发布时间】:2016-02-02 11:19:23
【问题描述】:

我正在使用 Newtonsoft.Json 序列化缓存值,我想知道是否有一种方法可以像从序列化中排除方法一样排除可执行属性?最好是一种全局设置的方法,这样我就不需要用属性标记数百个属性(我首先必须在数千个属性中找到)。

代码:

[Serializable]
public class Item
{
    public long Id { get; set; }

    public string Name { get; set; }

    public List<Image> Images { get; set; }

    public Image PrimaryImage { get { return Images[0]; } }
}

[Serializable]
public class Image
{
    public long Id { get; set; }

    public string FileName { get; set; }
}

错误:

Error getting value from 'PrimaryImage' on 'Item'.
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)

我还要提到 PrimaryImage 中的逻辑已被简化,因此解决方案是不要跳过使用该属性。这似乎是属性的一种很常见的用法,所以我觉得奇怪的是它还没有处理它。

【问题讨论】:

  • 您可以创建一个ContractResolverstackoverflow.com/questions/33258314/… 我提供的答案是针对忽略特定类型的属性,但可以根据您的需要进行修改。也可以全局设置,很方便。
  • @Ric 这是朝着正确方向迈出的一步,但您有什么建议可以区分简单数据容器的属性和可执行的属性吗?
  • 您将什么定义为可执行文件?
  • @Ric 似乎序列化程序对任何不是 { get; 的属性都有问题。放; } 自动实现的属性,所以这就是我的定义。任何定义了访问器的属性。
  • 我确信排除只读/只写属性很容易事实上这里是显示可用选项的文档newtonsoft.com/json/help/html/…

标签: c# json serialization properties


【解决方案1】:

试试这段代码(仅序列化 get-set 属性):

public static class NewtonsoftDefaultSettings
{
    public static JsonSerializerSettings CreateRelease()
    {
        return Create(Formatting.None);
    }

    public static JsonSerializerSettings CreateDebug()
    {
        return Create(Formatting.Indented);
    }

    private static JsonSerializerSettings Create(Formatting formatting)
    {
        return new JsonSerializerSettings
        {
            Formatting = formatting,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            ContractResolver = new MyContractResolver()
        };
    }
}

internal class MyContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        var members = base.GetSerializableMembers(objectType).Cast<PropertyInfo>().ToList();
        members.RemoveAll(x => !x.CanRead || !x.CanWrite);
        return members.Cast<MemberInfo>().ToList();
    }
}

最后:

var str = JsonConvert.SerializeObject(value, NewtonsoftDefaultSettings.CreateDebug());

【讨论】:

  • 这会根据其返回类型排除属性。我的问题不是返回什么类型的值,而是如何返回该值。
  • @Div1 您仍然需要提供有关“如何返回该值”的更多信息,除非您提供更多信息,否则我们无法猜测。
  • 当然,对不起,我在我的问题下面的 cmets 中更多地描述了这个问题。具体来说,序列化程序似乎对任何不是 { get; 的属性都有问题。放; } 自动实现的属性,所以我需要它来排除定义了访问器的属性。
  • 好的。我改变了我的代码。现在只有 get-set 属性被序列化。
  • 我还没有弄清楚到底是什么导致了这个问题。在我的代码中有多种情况,相同类型的属性有时有效,有时无效,我的快速测试无法缩小原因。无论如何,这个解决方案解决了我的问题,它还使序列化的值更小,省去了不必要的重复数据。
猜你喜欢
  • 2012-04-27
  • 2012-05-15
  • 1970-01-01
  • 2016-07-25
  • 2013-10-28
  • 2011-05-14
  • 2011-05-16
  • 2015-12-06
  • 1970-01-01
相关资源
最近更新 更多