-
Notifications
You must be signed in to change notification settings - Fork 0
Deserialization
RestSharp includes deserializers to process XML and JSON. Upon receiving a response, RestClient chooses the correct deserializer to use based on the Content Type returned by the server. The defaults can be overridden (see Customization). The built-in content types supported are:
- application/json – JsonDeserializer
- application/xml – XmlDeserializer
- text/json – JsonDeserializer
- text/xml – XmlDeserializer
-
*
– XmlDeserializer (all other content types not specified)
The default deserializers attempt to remove the pain of having to parse XML or JSON. This is done by mapping to plain-ol’ CLR objects. Your classes define how you want the returned data to be deserialized. Instead of traversing the data and searching for a matching property in your class, RestSharp uses your class as the starting point, looping through each publicly-accessible, writable property and searching for a corresponding element in the data returned.
NOTE: DataAnnotation/DataMember or other attributes are NOT supported by the default RestSharp Deserializers. In order to use those, you must implement and register your own IDeserializer that wraps a deserialization library compatible with those attributes.
For example, this XML would map to this class:
<Person>
<Name>John</Name>
<Id>28</Id>
</Person>
public class Person {
public string Name { get; set; }
public int Id { get; set; }
}
Or this JSON would map to the same Person class:
{
"Name": "John",
"Id": 28
}
- Primitives (int, short, long, etc)
- Decimal
- DateTime
- String
- Guid
- List<T>
- Nested classes
- Nullable versions of the above listed types
- Primitives
- Decimal
- DateTime
- String
- Guid
- List<T>
- Dictionary<T1, T2>
- Nested classes
- Nullable versions of the above listed types
When searching data for a matching element, the default XML deserializer will look for elements and attributes in the following order:
- Element with exact name match
- Element with name matching lower-cased property name
- Element with name matching camel-cased property name
- (Special case, see below)
- Element with underscores and dashes removed from name
- Attribute with exact name match
- Attribute with name matching lower-cased property name
- Attribute with name matching camel-cased property name
- Attribute with underscores and dashes removed from name
There is one special case where the value of an element will be returned. Only an example can explain it.
If the XML returned is like this:
<Response>Hello world</Response>
There’s no way to directly represent that in a C# class:
public class Response {
}
You need something to hold the value of the Response element. In this case, add a property called Value and it will be populated:
public class Response {
public string Value { get; set; }
}
This condition is checked for between searching for matching element names and matching attribute names.
When searching data for a matching element, the default JSON deserializer will look for elements in the following order:
- Exact name match
- Camel-cased version of property name
- Lower-cased version of property name
- Property name with underscores added (e.g. ProductId → Product_Id)
- Lower-cased version of “underscored” name (e.g. Product_id → product_id)
Two different types of lists are handled: parentless (inline) and regular (nested). For instance, both of the following XML structures
<?xml version="1.0" encoding="utf-8" ?> <InlineListSample> <image src="1.gif">value1</image> <image src="2.gif">value2</image> <image src="3.gif">value3</image> <image src="4.gif">value4</image> </InlineListSample>
<?xml version="1.0" encoding="utf-8" ?> <NestedListSample> <images> <image src="1.gif">value1</image> <image src="2.gif">value2</image> <image src="3.gif">value3</image> <image src="4.gif">value4</image> </images> </NestedListSample>
Will map to the following C# schema:
public class ListSample { public List<Image> Images { get; set; } }
public class Image { public string Src { get; set; } public string Value { get; set; } }
If by chance both element structures existed in the same document at the relevant point in the hierarchy, parented/nested/regular lists take priority.
RestSharp supports both List and Dictionary<string, T> when mapping to JSON arrays and dictionaries.
If RestRequest.DateFormat is specified the value is retrieved using DateTime.ParseExact using your specified format string.
If RestRequest.DateFormat is not specified, DateTime.Parse is used to evaluate the element value. If are dealing with a format that is not parsable with that method, change your property type to String and evaluate/process as need after retrieval.
If your request does not specify a date format via RestRequest.DataFormat RestSharp attempts to deserialize your DateTime property values using the following format strings (in this order, with InvariantCulture);
- “u”
- “s”
- “yyyy’-‘MM’-’dd’T’HH’:‘mm’:’ss’Z’”
- “yyyy-MM-ddTHH:mm:ssZ”
- “yyyy-MM-dd HH:mm:ssZ”
- “yyyy-MM-ddTHH:mm:ss”
- “yyyy-MM-ddTHH:mm:sszzzzzz”
The JsonSerializer supports the following JSON date styles by default. These are ignored if you specify RestRequest.DateFormat.
-
ISO –
{"Value":"1910-09-25T09:30:25Z"}
- Javascript Date Objects –
{"Value":new Date(-1870352975000)}
For JS date objects, the milliseconds are extracted and added to the Javascript epoch time and then adjusted for the time zone if specified.
You can write your own deserializers to handle content. The steps are as follows:
- Create a class and implement IDeserializer
- Register a handler and associated content type using RestClient.AddHandler(contentType, IDeserializer). If the content type is already registered, it will be overridden by your specified handler. You can remove all registered handlers by calling RestClient.ClearHandlers() or just one by calling RestClient.RemoveHandler(contentType).
When making requests with XML or JSON request bodies, you can specify your own implementation of ISerializer to use.
var request = new RestRequest();
request.RequestFormat = RequestFormat.Xml;
request.XmlSerializer = new SuperXmlSerializer(); // implements ISerializer
request.AddBody(person); // object serialized to XML using your custom serializer;