确定JSON可以反序列化成什么类型的对象

本文关键字:什么 类型 对象 反序列化 JSON 确定 | 更新日期: 2023-09-27 18:02:21

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

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

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

在这个时间点RadDock不是结构化的,这样有派生类只期望一个historicalJSONAttribute或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; }
}

确定JSON可以反序列化成什么类型的对象

CustomLocalSettingsJSON是HistoricalLocalSettingsJSON的子部分。

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

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 ...
}

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