locked
Issues with deserialization of restful responses into custom class RRS feed

  • Question

  • Hello, I am trying to develop some code with generics, the idea is following:

    We have plenty of API tests and each one of them requires some very long and complicated call, since they are hard to memorize I was thinking of a way to do that with classes. You create two classes with Request and Response and fill up the needed properties and serialize that into XML, JSON or FORM and get the results populated in the Response class.

    To make this happen I have two abstract classes - RESTfulRequest and RESTfulResponse.

    These two classes are to be inherited by any class that is going to be used for RESTful call.

    public abstract class RESTFulRequest
        {
    
            #region Public Fields
    
            public string Url { get; set; }
            public ContentType ContentType { get; set; }
            public List<KeyValue> CustomHeaders { get; set; }
    
            #endregion
    
            #region Public Constuctors
    
            public RESTFulRequest()
            {
                this.CustomHeaders = new List<KeyValue>();
            }
    
            #endregion
    
        }
    
     public class RESTFulResponseInternal
        {
            #region Public Constructors
    
            /// <summary>
            /// Initializes the class with the specified status code and content.
            /// </summary>
            /// <param name="statusCode">The http status code.</param>
            /// <param name="isSuccessStatusCode">A boolean value indicating if the http response was successful.</param>
            /// <param name="content">The http response content.</param>
            public RESTFulResponseInternal (HttpStatusCode statusCode, bool isSuccessStatusCode, string content)
            {
                StatusCode = statusCode;
                IsSuccessStatusCode = isSuccessStatusCode;
                Content = content;
            }
    
            #endregion
    
            #region Public Properties
    
            /// <summary>
            /// Gets http status code.
            /// </summary>
            public HttpStatusCode StatusCode { get; private set; }
    
            /// <summary>
            /// Gets a value indicating if the http response was successful.
            /// </summary>
            public bool IsSuccessStatusCode { get; private set; }
    
            /// <summary>
            /// Gets the http response content.
            /// </summary>
            public string Content { get; private set; }
    
            #endregion
        }


    Next I have an extension method for every class that inherits the Request class

    public static TResult POST<TResult>(this RESTFulRequest obj, string accessToken = "")
                where TResult : RESTFulResponse, new()
            {
                if (obj == null) return default(TResult);
    
                var url = obj.Url;
                var content = ContentProvider.GetContent(obj);
                var contentType = obj.ContentType.GetDisplayName();
                var headers = HeaderProvider.GetHeaders(accessToken, obj.CustomHeaders.ToArray());
    
                var result = RESTFul.PostInternal(obj.Url, content, contentType, headers);
    
                return RESTFul.ResponseProcessor<TResult>(result);
            }


    and after I get the response I have this method to populate the Reponse method

    private static TResult ResponseProcessor<TResult>(RESTFulResponseInternal result)
                where TResult : RESTFulResponse
            {
                if (result.IsSuccessStatusCode)
                {
                    var response = ContentProvider.Deserialize<TResult>(result.Content);
                    response.Response = result;
                    response.Map();
    
                    return response;
                }
                else
                {
                    throw new InvalidOperationException($"RESTful Exception: {result.StatusCode}\nError: {result.Content}");
                }
            }


    Everything works great! Just one case  found failing. If I have following JSON:

    [
      {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      },
      {
        "userId": 1,
        "id": 2,
        "title": "qui est esse",
        "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
      }
    }
    To Deserialize into TypiCodePostResponse class.

    public class TypiCodePostResponse : RESTFulResponse { public Post[] Posts { get; set; } public class Post { public int userId { get; set; } public int id { get; set; } public string title { get; set; } public string body { get; set; } } }


    Would not work with my logic

    I need a class with a List/Array of Posts inside. I dont want to make Posts Inheriting the RESTfulResponse class, because then all rest call metadata will be stored in each one of them, where I do not want that.

    Any ideas ?

    Thanks in advance,

    Martin

    Monday, July 2, 2018 11:10 PM

All replies

  • Hi Martin Nikolaev,

    Thank you for posting here.

    For your question, how do you define the class for json string in the response link you provided? If you want to serialize the json data with classes, you could copy the json data and do the steps below to generate classes automatically.

    Click Edit> Paste Special> Paste JSON As Classes.

     

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, July 3, 2018 7:21 AM
  • Hi Wendy,

    thanks for your reply, but my question is pure C# rather than VS functionality.

    Thanks anyway,

    Martin

    Tuesday, July 3, 2018 7:54 AM
  • Hi Martin Nikolaev,

    If you do not want the VS function, you could try to use JObject to deserialize json data without classes.

    Install Newtonsoft.Json from Manage NuGet Package.

    Here is a simple example about JObect for your reference.

    https://stackoverflow.com/questions/4535840/deserialize-json-object-into-dynamic-object-using-json-net

    https://stackoverflow.com/questions/4749639/deserializing-json-to-net-object-using-newtonsoft-or-linq-to-json-maybe

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Proposed as answer by Stanly Fan Wednesday, July 4, 2018 8:17 AM
    Tuesday, July 3, 2018 8:26 AM