web-dev-qa-db-fra.com

JSON.Net Ignore Property pendant la désérialisation

J'ai une classe mis en place comme suit:

public class Foo
{
    public string string1 { get; set; }
    public string string2 { get; set; }
    public string string3 { get; set; }
}

J'utilise Json.Net pour désérialiser la réponse Json suivante:

string json = "[{\"number1\": 1, \"number2\": 12345678901234567890, \"number3\": 3},      
{\"number1\": 9, \"number2\": 12345678901234567890, \"number3\": 8}]";

Code de désérialisation: 

List<Foo> foos = JsonConvert.DeserializeObject<List<Foo>>(json);

Le deuxième nombre dépasse un int-64, mais je ne me soucie pas vraiment de récupérer cette valeur. Existe-t-il un moyen de convertir la propriété 'number2' en chaîne ou de l'ignorer complètement pendant la désérialisation?

J'ai essayé d'ajouter l'attribut '[JsonConverter (typeof (string))]' à la propriété string2, mais je reçois le message d'erreur suivant: 'Erreur de création de System.String'. J'ai aussi essayé de définir le typeof (décimal).

J'ai aussi essayé d'utiliser [JsonIgnore] mais cela ne fonctionne pas.

25
FEXTWOLF

Vous pouvez utiliser la propriété MissingMemberHandling de l'objet JsonSerializerSettings.

Exemple d'utilisation:

var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

JsonConvert.DeserializeObject<YourClass>(jsonResponse, jsonSerializerSettings);

Plus d'infos ici .

26
Florin D. Preda

Cette solution de contournement est boiteuse, mais vous pouvez créer une méthode pour charger manuellement le JSON. Si le chargement de données est trop important sans désérialiseur automatique, supprimez simplement les nœuds que vous ne souhaitez pas. C'est beaucoup plus lent cependant.

public static List<Foo> FromJson(string input) {
    var json = JToken.Parse(input);
    json["key"].Remove();
    var foo = JsonConvert.DeserializeObject<List<Foo>>(json.ToString());

}

C'est un problème intéressant. Je me demande si quelqu'un a une meilleure solution à ce problème.

9
Dharun

Voici la méthode préférée de Newtonsoft Json pour ignorer une propriété sans avoir à modifier la classe en fonction de http://james.newtonking.com/json/help/index.html?topic=html/ReducingSerializedJSONSize.htm

Celui-ci est utilisé pour ignorer les propriétés de référence paresseuses de EF ou Linq2Sql

public class DynamicContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, 
        MemberSerialization memberSerialization)
    {
        Func<Type,bool> includeProperty = t => t.IsValueType || t.Namespace.StartsWith("System") && t.Namespace.StartsWith("System.Data")==false; 
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        var allProperties = properties.Select (p => new{p.PropertyName,Including=includeProperty(p.PropertyType), p.PropertyType});//.Dump("props");
        var warnProperties=allProperties.Where (a =>a.Including && a.PropertyType.IsValueType==false && a.PropertyType.Name.IsIgnoreCaseMatch("String")==false) ;

        //linq pad debugging helper
        //var propertyTypesSerializing= allProperties.Where (p => p.Including).Select (p => p.PropertyType).Distinct().OrderBy (p => p.Name).Dump();

        if(warnProperties.Any())
        {
            //LinqPad helper
            //Util.Highlight(warnProperties.ToArray()).Dump("warning flag raised, aborting");
            throw new ArgumentOutOfRangeException();
        }

        properties = properties.Where(p =>includeProperty(p.PropertyType)).ToList();
        return properties;
    }
}

Tous les appels .Dump() ne sont que des assistants de débogage de linqpad, pas des appels de méthode nécessaires.

exemple d'utilisation:

var inactives = from am in Aspnet_Memberships
        join mm in Member_members on am.UserId equals mm.Member_guid
        where mm.Is_active==false && mm.Org_id==1
        select new{am,mm};
        //inactives.Take(4).ToArray().Dump();
        var serialized = JsonConvert.SerializeObject(
            inactives.Skip(1).Select(i => i.mm).First(), 
            new  JsonSerializerSettings()
            {
                ContractResolver = new DynamicContractResolver(), 
                PreserveReferencesHandling = PreserveReferencesHandling.None,
                ReferenceLoopHandling= ReferenceLoopHandling.Ignore
            }); 
            //.Dump();
7
Maslow

Similaire à @ La solution de Maslow , vous pouvez utiliser un autre "ignorer" à usage général :

var jsonResolver = new IgnorableSerializerContractResolver();
// ignore your specific property
jsonResolver.Ignore(typeof(Foo), "string2");
// ignore single datatype
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };
3
drzaus

Ajout à la réponse drzaus: Vous pouvez utiliser la DefaultContractResolver il a suggéré .. juste dans sa CreateProperty utiliser property.Ignored = true; au lieu de property.ShouldSerialize, alors il est bon que vous passiez la JsonSerializerSettings à la fonction DeserializeObject ou la fonction SerializeObject.

0
Ohad Bitton