Cómo ignorar una propiedad en clase si es null, usando json.net


Estoy usando Json.NET para serializar una clase a JSON.

Tengo la clase así:

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; }
}

Quiero añadir un atributo JsonIgnore() a la propiedad Test2List solo cuando Test2List es null. Si no es null entonces quiero incluirlo en mi json.

 363
Author: Vito Gentile, 2011-06-28

10 answers

Según James Newton King: Si crea el serializador usted mismo en lugar de usar JavaScriptConvert, hay un NullValueHandling propiedad que puede establecer como ignorar.

Aquí hay una muestra:

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

Alternativamente, como sugiere @amit

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });
 476
Author: Mrchief,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-30 20:51:06

Una solución alternativa usando el atributo JsonProperty:

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

Como se ve en este documento en línea.

 625
Author: sirthomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-10 04:19:54

Similar a la respuesta de @sirthomas, JSON.NET también respeta la propiedad EmitDefaultValue en DataMemberAttribute:

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

Esto puede ser deseable si ya está utilizando [DataContract] y [DataMember] en su tipo de modelo y no desea agregar atributos específicos de JSON.NET.

 45
Author: Toby J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-10 20:37:10

Puede hacer esto para ignorar todos los nulos en un objeto que está siendo serializado, y cualquier propiedad nula no aparecerá en el JSON

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);
 17
Author: Chris Halcrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-06 19:20:18

Puedes escribir: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

También se encarga de no serializar propiedades con valores predeterminados (no solo null). Puede ser útil para enumeraciones, por ejemplo.

 11
Author: Er Vatsal D Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-13 15:19:02

Como se puede ver en este enlace en su sitio (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) Apoyo el uso de [Default()] para especificar valores predeterminados

Tomado del enlace

   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
// }
 10
Author: Mickey Perlstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 08:57:45

Una adaptación a la respuesta de @Mrchief / @amit, pero para personas que usan VB

 Dim JSONOut As String = JsonConvert.SerializeObject(
           myContainerObject, 
           New JsonSerializerSettings With {
                 .NullValueHandling = NullValueHandling.Ignore
               }
  )

Véase: " Inicializadores de objetos: Tipos Nombrados y Anónimos (Visual Basic)"

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

 4
Author: GlennG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-14 11:26:24

Exponer ligeramente la respuesta muy útil de GlennG (traducir la sintaxis de C # a VB.Net no siempre es "obvio") también puede decorar propiedades de clase individuales para administrar cómo se manejan los valores nulos. Si hace esto, no utilice las configuraciones JSONSERIALIZERS globales de la sugerencia de GlennG, de lo contrario anulará las decoraciones individuales. Esto es útil si desea que aparezca un elemento nulo en el JSON para que el consumidor no tenga que hacer ningún manejo especial. Si, por ejemplo, el consumidor necesita saber que una serie de elementos opcionales está normalmente disponible, pero actualmente está vacía... La decoración en la declaración de propiedad se ve así:

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

Para aquellas propiedades que no desea que aparezcan en el JSON change :=NullValueHandling.Include to :=NullValueHandling.Ignore. Por cierto - He encontrado que se puede decorar una propiedad para la serialización XML y JSON muy bien (simplemente ponerlos uno al lado del otro). Esto me da la opción de llamar al serializador XML en dotnet o al serializador NewtonSoft a voluntad-ambos trabajan lado a lado y mis clientes tienen la opción de trabajar con XML o JSON. Esto es slick como moco en un pomo de la puerta ya que tengo clientes que requieren ambos!

 0
Author: Destek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 17:34:21

Aquí hay una opción que es similar, pero proporciona otra opción:

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

Entonces, lo uso así:

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

La diferencia aquí es que:

  • Reduce el código repetido instanciando y configurando JsonSerializerSettings cada lugar que se utiliza.
  • Ahorra tiempo en la configuración de cada propiedad de cada objeto a serializado.
  • Todavía da a otros desarrolladores flexibilidad en las opciones de serialización, en lugar de tener la propiedad especificada explícitamente en un objeto.
  • Mi caso de uso es que el código es una biblioteca de terceros y no quiero forzar las opciones de serialización a los desarrolladores que querrían reutilizar mis clases.
  • Los posibles inconvenientes son que es otro objeto que otros desarrolladores tendrían que conocer, o si su aplicación es pequeña y este enfoque no importaría para una sola serialización.
 0
Author: Joe Mayo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-07 00:29:40
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
//you can add multiple settings and then use it
var bodyAsJson = JsonConvert.SerializeObject(body, Formatting.Indented, settings);
 0
Author: Suresh Bhandari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-08 21:15:46