确定JSON可以反序列化的对象类型?

时间:2011-07-18 18:24:26

标签: c# json

我将一些JSON从客户端传递回服务器端。

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

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

此时,RadDock的结构不会使派生类只期望历史JSONAttribute或customJSONAttribute。提供给RadDock的数据反映了它所持有的内容。我没有看到原因(但是?)围绕其可能的内容构建父控件。

然而,这在我的RadDock类中留下了以下问题:

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

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

我无法保证传递给HandleDialogClose的json数据是HistoricalLocalSettingsJSON。我是否应该预先为eventArgument添加一个标志,以指示它是哪种类型的数据?没有完整的重组,是否有更好的选择?

由于

我的课程:

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

现在,CustomLocalSettingsJSON是HistoricalLocalSettingsJSON的子部分。

2 个答案:

答案 0 :(得分:1)

一种可能性是创建一个上层建筑:

class ClientData {
    HistoricalLocalSettingsJSON historicalJSONAttributes;
    CustomLocalSettingsJSON customJSONAttributes;
}

然后将数据包装在模仿此项的js对象中,将一个或其他属性保留为空。

如果其中一个类是另一个类的子类,您还可以使用NewtonSoft javascript反序列化器的Populate方法来填充派生类的实例。如果您需要正确键入对象,这可能没有用,但您可以使用具有SubType属性的单个类重构对象模型。

但基本上你需要让解串器知道如何以这种方式处理数据。如果没有提前解析解析器,那就没有直接的方法可以做到这一点。

或者您也可以传递对象类型的名称..

修改

一种允许您添加信息参数但仍保持在一个屋檐下的一般方法是将其包装到具有两个属性的对象中,一个用于标识类型,另一个用于标识JSON的字符串数据。 (这是正确的 - 您将序列化它两次 - 首先是JSON字符串,然后是JSON字符串字符串,因此它可以作为字符串而不是JSON对象传递。)

这使您可以一致地反序列化响应,然后决定如何继续。

class ClientData {
    public string TypeName;
    public string Data;
}

...

ClientData interim = JsonConvert.DeserializeObject<ClientData>(json);
switch(interim.TypeName)  {
    // take the appropriate action for each type
    case "HistoricalLocalSettingsJSON ":
        historical = 
           JsonConvert.DeserializeObject<HistoricalLocalSettingsJSON >(interim.Data);
        break;
    case ...
}

答案 1 :(得分:0)

您可以将deserializeObject包装在try / catch块中,然后捕获反序列化程序在无法将json数据与您想要的类型匹配时抛出的特定异常。如果您只有两种可能的类型,则可以在第一个获得异常后尝试反序列化第二个类型。如果我的解释不够清楚,我可以稍后编写代码示例。