简体   繁体   English

反序列化Json Web API响应-嵌套对象

[英]Deserialize Json Web API Response - Nested objects

I am getting a Web API JSON Response via SSIS Script component, that is coming back in the following format: 我正在通过SSIS脚本组件获得Web API JSON响应,该响应以以下格式返回:

    {
  "Success": true,
  "Response": {
    "Applications": [
      {
        "App_ID": 1638486,
        "App_Ref": "Test Example",
        "Status": "Complete",
        "Error_Code": null,
        "Error_Message": null,
        "Create_Dt": "2014-05-14 03:09:01.030 +00:00",
        "Modify_Dt": "2014-05-14 03:10:59.757 +00:00",
        "Client_Name": "Silver Chef",
        "Client_Code": "SLVC01",
        "Centrelink_Status": "Receiving_Logons"
      },
      {
        "App_ID": 1637906,
        "App_Ref": "SME Demo",
        "Status": "Complete",
        "Error_Code": null,
        "Error_Message": null,
        "Create_Dt": "2015-10-08 03:07:26.793 +00:00",
        "Modify_Dt": "2015-10-08 03:23:32.833 +00:00",
        "Client_Name": "Silver Chef",
        "Client_Code": "SLVC01",
        "Centrelink_Status": "Receiving_Logons"
      },
      {
        "App_ID": 1585286,
        "App_Ref": "Test",
        "Status": "Receiving_Logons",
        "Error_Code": null,
        "Error_Message": null,
        "Create_Dt": "2015-12-04 03:12:49.617 +00:00",
        "Modify_Dt": "2015-12-04 03:12:49.617 +00:00",
        "Client_Name": "Silver Chef",
        "Client_Code": "SLVC01",
        "Centrelink_Status": "Receiving_Logons"
      }
],
    "Current_Dt": "2016-11-11 01:01:01.743 +00:00",
    "Last_App_Dt": "2016-10-03 22:48:56.397 +00:00",
    "Count": 500,
    "Total": 1870
  }
}

I have declared the following classes: 我声明了以下类:

     public class Application
        {
            public int App_ID { get; set; }
            public string App_Ref { get; set; }
            public string Status { get; set; }
            public int Error_Code { get; set; }
            public string Error_Message { get; set; }
            public DateTime Create_Dt { get; set; }
            public DateTime Modify_Dt { get; set; }
            public string Client_Name { get; set; }
            public string Client_Code { get; set; }
            public int Centrelink_Status { get; set; }

        }
        public class Response
        {
            public List<Application> Applications { get; set; }
            public string Current_Dt { get; set; }
            public string Last_App_Dt { get; set; }
            public int Count { get; set; }
            public int Total { get; set; }
        }

        public class RootObject
        {
            public bool Success { get; set; }
            public Response Response { get; set; }
        }

And this is the method that I am using to get the response. 
private RootObject GetWebServiceResult(string vAPIUrl)
    {

        string vAPIToken = Variables.APIToken;

        //Create Web Request
        HttpWebRequest apireq = (HttpWebRequest)WebRequest.Create(vAPIUrl);
        apireq.ContentType = "application/json";
        apireq.Method = "POST";

        string jsonPostStr = "{\"Settings\": {\"API_Token\": \"" + vAPIToken + "\"}, \"Payload\": {}}";
        byte[] postString = Encoding.UTF8.GetBytes(jsonPostStr);

        apireq.ContentLength = postString.Length;

        Stream jsonStream = apireq.GetRequestStream();

        jsonStream.Write(postString, 0, postString.Length);
        jsonStream.Close();

        // Get Web Response        
        HttpWebResponse apirsp = (HttpWebResponse)apireq.GetResponse();
        RootObject jsonResponse = null;

        Stream jsonRspStream = apirsp.GetResponseStream();
        string apiResponseString = null;

        using (StreamReader reader = new StreamReader(jsonRspStream)) 
        {
            apiResponseString = reader.ReadToEnd(); 
            Console.WriteLine(apiResponseString);
            reader.Close();
        }


        JavaScriptSerializer returnJson = new JavaScriptSerializer();

        //var serialJsonStr = returnJson.Serialize(apiResponseString);
        System.Windows.Forms.MessageBox.Show(apiResponseString);

        jsonResponse = returnJson.Deserialize<RootObject>(apiResponseString);

        return jsonResponse;

    }

My issue is that returnJson.Deserialize(apiResponseString); 我的问题是returnJson.Deserialize(apiResponseString); seems to return null and subsequently makes this fail. 似乎返回null,随后使此操作失败。

What am i missing? 我想念什么? i think i am slightly code blind at this stage. 我认为我在这个阶段有点代码盲。

Thanks in advance 提前致谢

There are a couple of problems with the Application class: Application类存在两个问题:

  • You have defined Application.Error_Code to be an integer: 您已将Application.Error_Code定义为整数:

     public int Error_Code { get; set; } 

    But in fact, in the JSON, it has a null value: 但实际上,在JSON中,它具有空值:

     "Error_Code": null, 

    Thus Error_Code needs to be a reference type ( string ) or nullable value type ( int? ) depending on what it holds when non-null. 因此, Error_Code必须为引用类型( string )或可为空的值类型( int? ),具体取决于其在非null时的状态。

  • You have defined Centrelink_Status as an int , but in the JSON it's a string: 您已将Centrelink_Status定义为int ,但是在JSON中它是一个字符串:

     "Centrelink_Status": "Receiving_Logons" 

    Thus it needs to be a string in the data model as well. 因此,它在数据模型中也必须是字符串。

Thus your Application class should look like: 因此,您的Application类应如下所示:

public class Application
{
    public int App_ID { get; set; }
    public string App_Ref { get; set; }
    public string Status { get; set; }
    public int? Error_Code { get; set; } // Or string, if not numeric
    public string Error_Message { get; set; }
    public DateTime Create_Dt { get; set; }
    public DateTime Modify_Dt { get; set; }
    public string Client_Name { get; set; }
    public string Client_Code { get; set; }
    public string Centrelink_Status { get; set; }
}

You might also want to make those DateTime properties be nullable if there is a chance for a null value in the JSON. 如果JSON中可能有null值,您可能还想使那些DateTime属性为可空。

Incidentally, when I tried to deserialize this JSON, I got an exception thrown, rather than a null value returned: 顺便说一句,当我尝试反序列化此JSON时,抛出了异常,而不是返回null值:

System.InvalidOperationException was unhandled
  Message="Cannot convert null to a value type."
  Source="System.Web.Extensions"
  StackTrace:

In your actual code, are you catching and swallowing exceptions? 在您的实际代码中,您是否正在捕获并吞下异常? That's a bad idea precisely because it tends to hide errors such as this. 这是一个坏主意,恰恰是因为它倾向于隐藏诸如此类的错误。 At the minimum, when debugging you should break whenever any exception is thrown including a first-chance exception - even though this is not the default behavior. 至少,在调试时,无论何时抛出任何异常(包括一次机会异常),都应中断-即使这不是默认行为。 See Managing Exceptions with the Debugger . 请参阅使用调试器管理异常 If you find there are certain types of exception that are frequently thrown and are irrelevant to debugging, you can selectively re-ignore them. 如果发现某些经常抛出的异常类型与调试无关,则可以有选择地重新忽略它们。 Had you done so this bug would have been more straightforward to track down. 如果这样做,则可以更轻松地找到此错误。 Admittedly, the error is not very explanatory, but it does give a hint. 诚然,该错误不是很容易解释,但确实给出了提示。 If you were to use to deserialize your JSON, the error message would be much clearer: 如果您要使用反序列化JSON,则错误消息会更加清晰:

Newtonsoft.Json.JsonSerializationException occurred
  Message="Error converting value {null} to type 'System.Int32'. Path 'Response.Applications[0].Error_Code', line 9, position 26."
  Source="Newtonsoft.Json"
  StackTrace:
       at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 986
  InnerException: System.InvalidCastException
       Message="Null object cannot be converted to a value type."
       Source="mscorlib"
       StackTrace:
            at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 979
       InnerException: 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM