我可以选择在运行时关闭JsonIgnore属性吗?

时间:2016-05-22 07:43:36

标签: c# .net json.net

我正在从一组类中使用Newtonsoft.Json创建一个JSON文件。创建的文件非常大,因此我为属性创建了JsonProperty以减小大小,并为某些数据类型添加了JsonIgnore和自定义格式。

结果是从24MB减少到1MB,这很好;但是,我希望选择在运行时生成完整版本或简化属性版本。

无论如何,我可以让串行器选择性地使用属性吗?

3 个答案:

答案 0 :(得分:33)

是的,可以使用自定义ContractResolver完成此操作。

您没有显示任何代码,因此我只是举个例子。我们假设我有一个课程Foo,如下所示。我希望序列化输出中包含IdName属性,但我绝对不会对AlternateNameColor感兴趣。我用[JsonIgnore]标记了那些人。我想要显示描述,但有时这可能会很长,所以我使用自定义JsonConverter来限制其长度。我还想在描述中使用较短的属性名称,因此我用[JsonProperty("Desc")]标记了它。

class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
    [JsonIgnore]
    public string AlternateName { get; set; }
    [JsonProperty("Desc")]
    [JsonConverter(typeof(StringTruncatingConverter))]
    public string Description { get; set; }
    [JsonIgnore]
    public string Color { get; set; }
}

当我序列化上面的一个实例时......

Foo foo = new Foo
{
    Id = 1,
    Name = "Thing 1",
    AlternateName = "The First Thing",
    Description = "This is some lengthy text describing Thing 1 which you'll no doubt find very interesting and useful.",
    Color = "Yellow"
};

string json = JsonConvert.SerializeObject(foo, Formatting.Indented);

...我得到了这个输出:

{
  "Id": 1,
  "Name": "Thing 1",
  "Desc": "This is some lengthy text describing Thing 1 "
}

现在,让我们说我有时想获得完整的JSON输出,而忽略了我的自定义。我可以使用自定义ContractResolver以编程方式"取消应用"来自班级的属性。这是解析器的代码:

class IgnoreJsonAttributesResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
        foreach (var prop in props)
        {
            prop.Ignored = false;   // Ignore [JsonIgnore]
            prop.Converter = null;  // Ignore [JsonConverter]
            prop.PropertyName = prop.UnderlyingName;  // restore original property name
        }
        return props;
    }
}

要使用解析器,我将其添加到JsonSerializerSettings并将设置传递给序列化器,如下所示:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new IgnoreJsonAttributesResolver();
settings.Formatting = Formatting.Indented;

string json = JsonConvert.SerializeObject(foo, settings);

输出现在包含被忽略的属性,并且描述不再被截断:

{
  "Id": 1,
  "Name": "Thing 1",
  "AlternateName": "The First Thing",
  "Description": "This is some lengthy text describing Thing 1 which you'll no doubt find very interesting and useful.",
  "Color": "Yellow"
}

此处完整演示:https://dotnetfiddle.net/WZpeWt

答案 1 :(得分:1)

杰森支持我们忽视不想要回归的财产。 实施例

class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string AlternateName { get; set; }    
}

如何使用它:

Foo foo = new Foo
{
    Id = 1,
    Name = "Thing 1",
    AlternateName = null,   
};

string json = JsonConvert.SerializeObject(foo);

答案 2 :(得分:0)

如果您愿意使用F#(或只是使用未针对C#优化的API),则FSharp.JsonSkippable库包含通用包装类型,可让您以简单且强类型化的方式控制是否包含序列化时确定给定的属性(并确定反序列化时是否确定是否包含属性),此外,还应控制/确定是否为可空性排除。 (完全公开:我是图书馆的作者。)