es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

JsonConvert.PopulateObject establece las propiedades int en 0 si no hay ningún valor.

Intenté poblar un objeto desde JSON con Newtonsoft.Json (v13) y algunas propiedades de este objeto no son requeridas. Espero que las propiedades no requeridas se mantengan como “null”, para que cuando las serialice nuevamente, sean ignoradas con [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] y no aparezcan en el resultado JSON. Pero cuando poblé mi objeto, las propiedades de tipo entero que no estaban presentes en mi JSON se establecieron en 0 por defecto en lugar de null como otros valores de tipo.

El contenido del archivo jsonData.txt:

{
“name”: “name”
}

El código de ejemplo:

public class MyClass
{
[JsonProperty(Required = Required.Always)]
public string name { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string prop1 { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int prop2 { get; set; }

public Myclass(){}

}

string myClassJson = File.ReadAllText(“jsonData.txt”);

MyClass myClassObj = new MyClass();

JsonConvert.PopulateObject(myClassJson, myClassObj);

string jsonFromMyClassObjSerialized = JsonConvert.SerializeObject(myClassObj);

El resultado de jsonFromMyClassObjSerialized:

{
“name”: “name”,
“prop2”: 0
}

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para asegurarse de que las propiedades int se mantengan como null en lugar de 0 al poblar el objeto con Newtonsoft.Json, es necesario establecer el valor predeterminado de las propiedades int como null en la definición de la clase:

    public class MyClass
    {
        [JsonProperty(Required = Required.Always)]
        public string Name { get; set; }
    
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string Prop1 { get; set; }
    
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
        [JsonConverter(typeof(NullIntConverter))]
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public int? Prop2 { get; set; }
    
        public MyClass(){}
    }
    

    En el código anterior, agregamos los siguientes atributos a la propiedad prop2:

    • [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] – esto asegura que el valor predeterminado de esta propiedad se ignore y se llene con null en su lugar.
    • [JsonConverter(typeof(NullIntConverter))] – esto indica a Newtonsoft.Json que use un convertidor personalizado para convertir el valor null a int en lugar de utilizar la conversión predeterminada.
    • [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] – esto indica a Newtonsoft.Json que ignore los valores null al serializar el objeto.

    A continuación, necesitamos definir el convertidor personalizado:

    public class NullIntConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(int?) || objectType == typeof(int));
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return null;
            }
    
            return Convert.ToInt32(reader.Value);
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
            }
            else
            {
                writer.WriteValue(value);
            }
        }
    }
    

    En el convertidor anterior, verificamos si el valor es null y devolvemos null si lo es. De lo contrario, convertimos el valor a int utilizando Convert.ToInt32.

    Con la definición de clase y el convertidor actualizados, el resultado de jsonFromMyClassObjSerialized ahora debería ser:

    {
        "name": "name"
    }
    

    Esto se debe a que la propiedad int prop2 ahora es null y se ignora al serializar debido al atributo NullValueHandling = NullValueHandling.Ignore.

Comments are closed.