2011-07-18 3 views
1

Je repasse du JSON du côté client vers le côté serveur.Détermination du type d'objet que JSON peut désérialiser en?

if (historicalJSONAttributes != null) { 
    $find(ajaxManagerID).ajaxRequestWithTarget(radDock.get_uniqueID(), $.toJSON(historicalJSONAttributes)); 
} 

ou

if (customJSONAttributes!= null) { 
    $find(ajaxManagerID).ajaxRequestWithTarget(radDock.get_uniqueID(), $.toJSON(customJSONAttributes)); 
} 

A ce moment Raddock n'est pas structuré de telle sorte qu'il existe des classes dérivées attendent seulement historicalJSONAttribute ou customJSONAttribute. Les données fournies à RadDock reflètent le contenu qu'il contient. Je n'ai pas vu de raison (encore?) De structurer un contrôle parent autour de son contenu possible.

Cela me laisse la question suivante, cependant, à l'intérieur de ma classe Raddock:

public void RaisePostBackEvent(string eventArgument) 
{ 
    HandleDialogClose(eventArgument); 
} 

private void HandleDialogClose(string json) 
{ 
    JsonConvert.DeserializeObject<HistoricalLocalSettingsJSON>(json); 
} 

Je ne garantit que les données JSON transmises à HandleDialogClose est HistoricalLocalSettingsJSON. Devrais-je pré-utiliser mon eventArgument avec un indicateur pour indiquer le type de données? Y a-t-il une meilleure option sans une restructuration complète?

Merci

Mes classes:

[DataContract] 
public class HistoricalLocalSettingsJSON 
{ 
    private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

    public HistoricalLocalSettingsJSON() { } 

    public HistoricalLocalSettingsJSON(string commandName, string dockID, string refreshEnabled, string refreshInterval, string chartType, string timeRestrictionEnabled, string timeStart, string timeEnd, string dataPointsEnabled) 
    { 
     Logger.InfoFormat("Command Name: {0}, DockID: {1}, RefreshEnabled: {2}, RefreshInterval: {3}, ChartType: {4}, TimeRestrictionEnabled: {5}, TimeStart: {6}, TimeEnd: {7}, DataPointsEnabled: {8}", 
      commandName, dockID, refreshEnabled, refreshInterval, chartType, timeRestrictionEnabled, timeStart, timeEnd, dataPointsEnabled); 

     CommandName = commandName; 
     DockID = dockID; 
     RefreshEnabled = bool.Parse(refreshEnabled); 
     RefreshInterval = int.Parse(refreshInterval); 
     ChartType = (Charts)Enum.Parse(typeof(Charts), chartType); 
     TimeRestrictionEnabled = bool.Parse(timeRestrictionEnabled); 
     TimeStart = timeStart; 
     TimeEnd = timeEnd; 
     DataPointsEnabled = !string.IsNullOrEmpty(dataPointsEnabled) ? bool.Parse(dataPointsEnabled) : false; 
    } 

    [DataMember(Name = "CommandName")] 
    public string CommandName { get; set; } 

    [DataMember(Name = "DockID")] 
    public string DockID { get; set; } 

    [DataMember(Name = "RefreshEnabled")] 
    public bool RefreshEnabled { get; set; } 

    [DataMember(Name = "RefreshInterval")] 
    public int RefreshInterval { get; set; } 

    [DataMember(Name = "ChartType")] 
    public Charts ChartType { get; set; } 

    [DataMember(Name = "TimeRestrictionEnabled")] 
    public bool TimeRestrictionEnabled { get; set; } 

    [DataMember(Name = "TimeStart")] 
    public string TimeStart { get; set; } 

    [DataMember(Name = "TimeEnd")] 
    public string TimeEnd { get; set; } 

    [DataMember(Name = "DataPointsEnabled")] 
    public bool DataPointsEnabled { get; set; } 
} 

[DataContract] 
public class CustomLocalSettingsJSON 
{ 
    private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

    public CustomLocalSettingsJSON() { } 

    public CustomLocalSettingsJSON(string commandName, string dockID, string refreshEnabled, string refreshInterval, string chartType) 
    { 
     Logger.InfoFormat("Command Name: {0}, DockID: {1}, RefreshEnabled: {2}, RefreshInterval: {3}, ChartType: {4}", 
      commandName, dockID, refreshEnabled, refreshInterval, chartType); 

     CommandName = commandName; 
     DockID = dockID; 
     RefreshEnabled = bool.Parse(refreshEnabled); 
     RefreshInterval = int.Parse(refreshInterval); 
     ChartType = (Charts)Enum.Parse(typeof(Charts), chartType); 
    } 

    [DataMember(Name = "CommandName")] 
    public string CommandName { get; set; } 

    [DataMember(Name = "DockID")] 
    public string DockID { get; set; } 

    [DataMember(Name = "RefreshEnabled")] 
    public bool RefreshEnabled { get; set; } 

    [DataMember(Name = "RefreshInterval")] 
    public int RefreshInterval { get; set; } 

    [DataMember(Name = "ChartType")] 
    public Charts ChartType { get; set; } 
} 

En l'état actuel CustomLocalSettingsJSON est une sous-section de HistoricalLocalSettingsJSON.

Répondre

1

Une possibilité est de créer une superstructure:

class ClientData { 
    HistoricalLocalSettingsJSON historicalJSONAttributes; 
    CustomLocalSettingsJSON customJSONAttributes; 
} 

Ensuite, il suffit envelopper vos données dans un objet js qui imite ce, en laissant une ou les autres propriétés null.

Si l'une des classes est une sous-classe de l'autre, vous pouvez également utiliser la méthode Populate de NewtonSoft javascript deserializer pour remplir une instance de la classe dérivée. Cela peut ne pas être utile si vous avez besoin de taper l'objet correctement, mais vous pouvez simplement restructurer le modèle d'objet avec une seule classe qui a une propriété SubType ou quelque chose. Mais en gros, vous allez devoir laisser le désérialiseur savoir quoi faire avec les données d'une manière ou d'une autre. À moins d'écrire un analyseur pour le comprendre à l'avance, il n'y a pas de moyen direct de le faire à ma connaissance.

Ou vous pouvez simplement passer le nom du type d'objet trop ..

modifier

Une approche générale qui vous permet d'ajouter un paramètre d'information, mais toujours garder sous un même toit, serait pour l'envelopper dans un objet avec deux propriétés, une pour identifier le type, puis l'autre qui est une chaîne de données JSON. (C'est vrai - vous le sérialiseriez deux fois - d'abord à une chaîne JSON, puis à une chaîne de caractères JSON, de sorte qu'il peut être passé comme une chaîne plutôt qu'un objet JSON.

Cela vous permet de désérialiser la réponse de manière cohérente, puis de décider comment procéder.

+0

Lecture à propos des propriétés Populate et SubType maintenant. Je ne suis pas sûr à 100% que je veux créer la dépendance que CustomLocalSettingsJSON est une sous-section de HistoricalLocalSettingsJSON. La déclaration est vraie actuellement, mais rien n'empêche le boss de changer d'avis plus tard et je détesterais perdre beaucoup de travail en faisant cette supposition. Merci pour les pointeurs. :) –

+0

Voir modifier .. une autre pensée pour un moyen général de le gérer. Vous pouvez sérialiser deux fois les données et les transmettre en tant que chaîne dans un objet général. Cela permet au code du serveur de se désintégrer de manière cohérente, puis d'utiliser l'heure correcte de l'objet pour la désérialisation finale des données. –

+0

Merci pour cela. Cela semble bon et plus intuitif. Je vais l'utiliser. :) –

0

Vous pouvez placer deserializeObject dans un bloc try/catch, puis intercepter l'exception spécifique que le désérialiseur lance lorsqu'il ne peut pas faire correspondre les données json au type souhaité. Si vous n'avez que deux types possibles, vous pouvez essayer de désérialiser le second après avoir obtenu une exception pour le premier. Je peux écrire un code plus tard si mon explication n'est pas assez claire.

+1

:) Bien sûr, je préférerais faire un pré-traitement plutôt que d'utiliser des exceptions comme moyen de navigation par code. Mon implémentation actuelle est quelque chose comme historicJSONAttributes ["CommandName"] = "Mettre à jour les paramètres locaux historiques"; Ensuite, côté serveur, j'appelle string.Split (','), parse le drapeau, et réagis en conséquence. Juste semble un peu ringard .. –

+0

Le problème est que vous avez déjà une situation moins qu'idéale. Pardonnez-moi si j'ai manqué cela mais y at-il une raison particulière pour laquelle vous ne pouvez pas avoir une méthode séparée pour ces deux types? – Garvin

Questions connexes