如何使用json.net忽略类中的属性null

时间:2011-06-28 14:14:55

标签: c# json.net

我正在使用Json.NET将类序列化为JSON。

我有这样的课程:

class Test1
{
    [JsonProperty("id")]
    public string ID { get; set; }
    [JsonProperty("label")]
    public string Label { get; set; }
    [JsonProperty("url")]
    public string URL { get; set; }
    [JsonProperty("item")]
    public List<Test2> Test2List { get; set; }
}

我希望仅在JsonIgnore()Test2List时向Test2List属性添加null属性。如果它不为null,那么我想将它包含在我的json中。

14 个答案:

答案 0 :(得分:759)

使用JsonProperty属性的替代解决方案:

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
// or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]

// or for all properties in a class
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]

this online doc中所示。

答案 1 :(得分:579)

根据James Newton King的说法:如果您自己创建序列化程序而不是使用JavaScriptConvert,则可以设置NullValueHandling property来忽略。

以下是一个示例:

JsonSerializer _jsonWriter = new JsonSerializer {
                                 NullValueHandling = NullValueHandling.Ignore
                             };

或者,正如@amit

所建议的那样
JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });

答案 2 :(得分:51)

与@ sirthomas的答案类似,JSON.NET也尊重DataMemberAttribute上的the EmitDefaultValue property

[DataMember(Name="property_name", EmitDefaultValue=false)]

如果您已在模型类型中使用[DataContract][DataMember]并且不想添加特定于JSON.NET的属性,则可能需要这样做。

答案 3 :(得分:24)

你可以写:[JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

它还负责不使用默认值(不仅为null)序列化属性。例如,它可用于枚举。

答案 4 :(得分:20)

您可以这样做来忽略您要序列化的对象中的所有空值,然后任何空属性都不会出现在JSON中

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);

答案 5 :(得分:10)

可以在他们网站上的这个链接中看到(http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size。 aspx)我支持使用[Default()]指定默认值

取自链接

   public class Invoice
{
  public string Company { get; set; }
  public decimal Amount { get; set; }

  // false is default value of bool
  public bool Paid { get; set; }
  // null is default value of nullable
  public DateTime? PaidDate { get; set; }

  // customize default values
  [DefaultValue(30)]
  public int FollowUpDays { get; set; }
  [DefaultValue("")]
  public string FollowUpEmailAddress { get; set; }
}


Invoice invoice = new Invoice
{
  Company = "Acme Ltd.",
  Amount = 50.0m,
  Paid = false,
  FollowUpDays = 30,
  FollowUpEmailAddress = string.Empty,
  PaidDate = null
};

string included = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0,
//   "Paid": false,
//   "PaidDate": null,
//   "FollowUpDays": 30,
//   "FollowUpEmailAddress": ""
// }

string ignored = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0
// }

答案 6 :(得分:4)

适应@Mychief的/ @ amit的答案,但适用于使用VB的人

(?s)(?=protocol udp).*(inactivity-timeout (?!1800))

请参阅:  "Object Initializers: Named and Anonymous Types (Visual Basic)"

https://msdn.microsoft.com/en-us/library/bb385125.aspx

答案 7 :(得分:0)

稍微阐述一下GlennG非常有用的答案(将语法从C#转换为VB.Net并不总是“显而易见”)你还可以修饰单个类属性来管理如何处理空值。如果这样做,请不要使用GlennG建议的全局JsonSerializerSettings,否则它将覆盖单个装饰。如果您希望在JSON中显示空项目,那么这会派上用场,因此消费者不必进行任何特殊处理。例如,如果消费者需要知道一系列可选项目通常是可用的,但目前是空的...... 财产声明中的装饰如下:

<JsonPropertyAttribute("MyProperty", DefaultValueHandling:=NullValueHandling.Include)> Public Property MyProperty As New List(of String)

对于那些您不希望在JSON更改中显示的属性:= NullValueHandling.Include := NullValueHandling.Ignore 。 顺便说一句 - 我发现你可以为XML和JSON序列化装饰一个属性就好了(只需将它们放在彼此旁边)。这使我可以随意调用dotnet中的XML序列化程序或NewtonSoft序列化程序 - 两者并排工作,我的客户可以选择使用XML或JSON。由于我的顾客需要两者,所以这就像门把手上的鼻涕一样光滑!

答案 8 :(得分:0)

这是一个类似的选项,但提供了另一种选择:

public class DefaultJsonSerializer : JsonSerializerSettings
{
    public DefaultJsonSerializer()
    {
        NullValueHandling = NullValueHandling.Ignore;
    }
}

然后,我这样使用它:

JsonConvert.SerializeObject(postObj, new DefaultJsonSerializer());

这里的区别在于:

  • 通过实例化和配置JsonSerializerSettings每个使用过的地方来减少重复的代码。
  • 节省配置每个要序列化的对象的每个属性的时间。
  • 仍然为其他开发人员提供了序列化选项的灵活性,而不是在可重用对象上明确指定属性。
  • 我的用例是代码是第三方库,我不想强​​迫那些想要重用我的类的开发人员使用序列化选项。
  • 潜在的缺点是,它是其他开发人员需要了解的另一个对象,或者如果您的应用程序很小,这种方法对于单个序列化并不重要。

答案 9 :(得分:0)

在.Net Core中,这现在变得容易得多。在您的startup.cs中,只需添加json选项,即可在此处配置设置。


public void ConfigureServices(IServiceCollection services)

....

services.AddMvc().AddJsonOptions(options =>
{
   options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;               
});

答案 10 :(得分:0)

使用Json.NET

list = soup.find_all('tr')
    for item in list:
        print(item.attrib) #continuously prints none

结果将是:

list = soup.find_all('tr')
        for item in list:
            print(item.find('tr')['bicolor'])

答案 11 :(得分:0)

借助System.Text.Json和.NET Core 3.0,它为我工作了:

var jsonSerializerOptions = new JsonSerializerOptions()
{
    IgnoreNullValues = true
};
var myJson = JsonSerializer.Serialize(myObject, jsonSerializerOptions );

答案 12 :(得分:0)

这不能完全回答原始问题,但是根据使用情况可能会证明是有用的。 (而且由于搜索后我在这里清醒,对其他人可能会有用。)

根据我最近的经验,我正在使用PATCH api。如果指定了属性但没有给出值(由于是js,则为null / undefined),则该属性和值将从正在修补的对象中删除。因此,我一直在寻找一种方法来有选择地构建一个对象,该对象可以以一种可行的方式进行序列化。

我记得曾经看过ExpandoObject,但是直到今天才有真正的用例。这使您可以动态地构建对象,因此除非您希望在其中存在null属性,否则您将没有null属性。

Here是一个工作提琴,下面的代码。

结果:

Standard class serialization
    noName: {"Name":null,"Company":"Acme"}
    noCompany: {"Name":"Fred Foo","Company":null}
    defaultEmpty: {"Name":null,"Company":null}
ExpandoObject serialization
    noName: {"Company":"Acme"}
    noCompany: {"name":"Fred Foo"}
    defaultEmpty: {}

代码:

using Newtonsoft.Json;
using System;
using System.Dynamic;
                    
public class Program
{
    public static void Main()
    {
        SampleObject noName = new SampleObject() { Company = "Acme" };
        SampleObject noCompany = new SampleObject() { Name = "Fred Foo" };
        SampleObject defaultEmpty = new SampleObject();
        
        
        Console.WriteLine("Standard class serialization");
        Console.WriteLine($"    noName: { JsonConvert.SerializeObject(noName) }");
        Console.WriteLine($"    noCompany: { JsonConvert.SerializeObject(noCompany) }");
        Console.WriteLine($"    defaultEmpty: { JsonConvert.SerializeObject(defaultEmpty) }");
        
        
        Console.WriteLine("ExpandoObject serialization");
        Console.WriteLine($"    noName: { JsonConvert.SerializeObject(noName.CreateDynamicForPatch()) }");
        Console.WriteLine($"    noCompany: { JsonConvert.SerializeObject(noCompany.CreateDynamicForPatch()) }");
        Console.WriteLine($"    defaultEmpty: { JsonConvert.SerializeObject(defaultEmpty.CreateDynamicForPatch()) }");
    }
}

public class SampleObject {
    public string Name { get; set; }
    public string Company { get; set; }
    
    public object CreateDynamicForPatch()
    {
        dynamic x = new ExpandoObject();
        
        if (!string.IsNullOrWhiteSpace(Name))
        {
            x.name = Name;
        }
        
        if (!string.IsNullOrEmpty(Company))
        {
            x.Company = Company;
        }
        
        return x;
    }
}

答案 13 :(得分:-1)

new Handler().postDelayed(theRunnable, 1000);