Comment puis-je faire JSON.NET ignorer les relations d'objet?

Je suis en train de travailler sur un Entity Framework projet. Je veux sérialiser un tas de l'entité des instances de classe. J'ai lié ces ensemble dans une classe de conteneur:

public class Pseudocontext
{
    public List<Widget> widgets;
    public List<Thing> things;

Etc... c'est une instance de cette classe que je suis en tentant de sérialiser. Je veux JSON.NET pour sérialiser les membres de chaque entité instance de classe qui sont en fait des colonnes dans la base de données. Je ne veux pas qu'il tente même de sérialiser les références de l'objet.

En particulier, les classes d'entité ont des membres virtuels qui me permettent d'écrire du code C# qui permet de naviguer tous mes inter-entités, relations, sans se soucier de réelles valeurs de clé, joint, etc., et je veux JSON.NET pour ignorer les parties associées de mes classes d'entité.

Sur la surface, il semble y avoir un JSON.NET option de configuration qui fait exactement de quoi je parle:

JsonSerializer serializer = new JsonSerializer();
serializer.PreserveReferencesHandling = PreserveReferencesHandling.None;

Malheureusement, JSON.NET semble ignorer le deuxième énoncé ci-dessus.

J'ai effectivement trouvé une page web (http://json.codeplex.com/workitem/24608) où quelqu'un d'autre a le même problème à l'attention de James Newton-King lui-même, et sa réponse (dans son intégralité) a été "Rédiger un contrat personnalisé de résolution."

Aussi inadéquate que je trouve que la réponse, j'ai été de tenter de suivre ses conseils. J'aimerais beaucoup être en mesure de rédiger un "contrat de résolution", qui ignorait tout, sauf les types primitifs, des cordes, des objets DateTime, et de ma propre Pseudocontext classe avec les Listes qu'il contient directement. Si quelqu'un a un exemple de quelque chose qui, au moins, ressemble à cela, il peut être tout ce dont j'ai besoin. C'est ce que j'ai trouvé sur mon propre:

public class WhatDecadeIsItAgain : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        JsonContract contract = base.CreateContract(objectType);
        if (objectType.IsPrimitive || objectType == typeof(DateTime) || objectType == typeof(string)
            || objectType == typeof(Pseudocontext) || objectType.Name.Contains("List"))
        {
            contract.Converter = base.CreateContract(objectType).Converter;
        }
        else
        {
            contract.Converter = myDefaultConverter;
        }
        return contract;
    }
    private static GeeThisSureTakesALotOfClassesConverter myDefaultConverter = new GeeThisSureTakesALotOfClassesConverter();
}

public class GeeThisSureTakesALotOfClassesConverter : Newtonsoft.Json.Converters.CustomCreationConverter<object>
{
    public override object Create(Type objectType)
    {
        return null;
    }
}

Quand je tente d'utiliser le haut (par la mise en sérialiseur.ContractResolver à une instance de WhatDecadeIsItAgain avant de sérialisation), j'obtiens des erreurs de dépassement de mémoire lors de la sérialisation qui indiquent que JSON.NET rencontre des boucles de référence que ne jamais mettre fin (en dépit de mes efforts pour faire JSON.NET simplement ignorer les références de l'objet).

Je pense que mon "contrat personnalisé résolution" peut-être tort. Comme indiqué ci-dessus, il est construit autour du principe que je doit retourner la valeur par défaut de "contrat" pour les types, je ne veux sérialiser, et un "contrat" qui retourne "null" pour tous les autres types.

Je n'ai aucune idée de comment corriger ces hypothèses sont, cependant, et il n'est pas facile à raconter. L'JSON.NET le design est très largement basé sur la mise en œuvre de l'héritage, redéfinition de méthode, etc.; Je ne suis pas beaucoup d'une La programmation orientée objet gars, et je trouve que ce genre de conception assez obscure. Ont-il un "contrat personnalisé résolveur" de l'interface que j'ai pu mettre en œuvre, Visual Studio 2012 serait capable d'écraser les méthodes requises très rapidement, et j'imagine que j'aurais peu de mal à remplir les talons avec une logique réelle.

J'aurais pas de problème d'écriture, par exemple, une méthode qui renvoie "vrai" si je veux sérialiser un objet de fourni et de type "false" sinon. Je suis peut-être raté quelque chose, mais j'ai pas trouvé la méthode pour remplacer, et je n'ai pas été en mesure de trouver l'hypothétique interface (ICustomContractResolver ?) qui serait me dire ce que je suis censé faire dans le dernier extrait de code inséré ci-dessus.

Aussi, je me rends compte qu'il y a JSON.NET attributs ([JsonIgnore]?) qui sont conçus pour faire face à des situations de ce genre. Je ne peux pas vraiment utiliser cette approche, depuis que je suis en utilisant un modèle "d'abord". Sauf si je décide de déchirer l'ensemble de mon projet d'architecture, de mes classes d'entité sont générés automatiquement, ils ne contiennent JsonIgnore attributs, ni ce que je me sens à l'aise d'édition automatisée de classes pour contenir ces attributs.

D'ailleurs, pendant un temps, je ne les choses ont-elles mis en place pour sérialiser les références de l'objet, et j'étais juste en ignorant tout le superflu "ref $" et "$id" données JSON.NET était de retour dans sa sérialisation de sortie. J'ai abandonné cette approche, pour le moment du moins, parce que (précipitamment) sérialisation commencé à prendre une quantité excessive de temps (~45 minutes pour arriver ~5 MO de JSON).

Je n'ai pas été en mesure de lier ce soudain changement dans la performance de retour à quelque chose de spécifique que j'ai fait. Si quoi que ce soit, le volume de données dans ma base de données est plus bas aujourd'hui qu'il ne l'était lors de la sérialisation était réellement terminer dans un délai raisonnable. Mais je serais plus qu'heureux, avec un retour à la statu quo ante (dans lequel j'étais juste avoir à ignorer "ref$", "$id", etc.) si cet objectif pouvait être atteint.

À ce point, je suis aussi ouvert à la perspective d'utiliser une autre librairie JSON, ou d'une stratégie différente, tout à fait. Je sens que je pourrais simplement utiliser StringBuilder, Système.Réflexion, etc. et de venir avec ma propre solution maison... mais n'est-ce pas JSON.NET censé être en mesure de gérer ce genre de chose assez facilement??

InformationsquelleAutor user1172763 | 2014-01-22