Custom Serialization/Deserialization in RestSharp 108 - c#

In updating from RestSharp 106 to 108 I've been unable to come up with an elegant replacement for the following. I've looked at the migration documentation to no avail. There is a good chance I've missed something obvious.
Existing code that works in v106, which covered both XML and JSON
Class A
using RestSharp.Deserializers;
[DeserializeAs(Name = "response")]
public class ACertainResponse
{
public string SomeProp {get; set;}
//Etc
}
//JSON Payload {"response" : {"SomeProp" : "Some Value"}}
Class B
using RestSharp.Serializers;
[SerializeAs(Name = "request")]
public class SomeRequest
{
public string SomeProp {get; set;}
//Etc
}
//Resulting in :
//{"request" : { "SomeProp" : "A Value" } }
I've found [JsonPropertyName("customName")], however, as the name suggests that is for properties only.

Whilst I was unable to find a one size fits all solution as previouslt provided I was able to get it working by setting attributes for XML or JSON serialization explicitly. These attributes cover bother serialization and deserialization:
JSON
using System.Text.Json.Serialization;
[JsonSerializable(typeof(LeadspediaRequest), TypeInfoPropertyName = "response")]
public class ACertainResponse
{
public string SomeProp {get; set;}
//Etc
}
XML
using System.Xml.Serialization;
[XmlRoot(ElementName = "response")]
[XmlType("response")]
public class SomeRequest
{
public string SomeProp {get; set;}
//Etc
}

Related

Newtonsoft.Json NullValueHandling=Ignore doesn't seem to work

C# with Newtonsoft.Json 13.0.2. I am deserializing a JSON string as such
var car = JsonConvert.DeserializeObject<Car>(resp);
where resp looks like this:
{
"perf": {
"perfRef": null,
"perfTest": {
"value": 1.2,
"unit": "percent"
}
}
}
My class looks like this:
public partial class perf
{
[Newtonsoft.Json.JsonProperty("perfRef", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public PerfRef perfRef { get; set; }
[Newtonsoft.Json.JsonProperty("perfTest", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public PerfTest perfTest { get; set; }
}
But I keep getting an exception
Newtonsoft.Json.JsonSerializationException: Required property 'perfRef' expects a non-null value. Path 'perf'
I don't get why this is happening. I thought the NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore would override any 'Required' option. Am I just misinterpreting how the decorators work?
you have Required which means you cannot have a null value for the perfRef
property.
there are ways to solve this.
either remove Required or provide the value to this property or set the Required attribute to AllowNull or Default.
Note: NullValueHandling Ignore means that null values will be ignored when serializing and deserializing JSON.
Could it be that the cause is that the json-string is wrapped with {"Perf": {...}} and you need an additional class to deserialize it.
My sample array [...] has two json-strings. Both contain the same object {...}
the first wraps it with {"Perf": {...}} like your sample
the second does not.
[
{"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}},
{"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
]
You can deserialize the first json string json[0] = {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}} using a class that acts as a wrapper (here JsonResponse):
// to deserialize
// {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}}
public class JsonResponse{
public Perf Perf {get; set;}
}
// use
JsonResponse resp0 = JsonConvert.DeserializeObject<JsonResponse>(json[0]);
If the json-string would not be wrapped then there is no need for a wrapper class
// to deserialize json[1]
// {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
// use
Perf resp1 = JsonConvert.DeserializeObject<Perf>(json[1]);
This is a lingpad-program that deserializes both json strings:
void Main()
{
// for {"Perf": {...}} a wrapper class is needed
JsonResponse withWrap = JsonConvert.DeserializeObject<JsonResponse>(GetResp()[0]);
// for {...} not
Perf noWrap = JsonConvert.DeserializeObject<Perf>(GetResp()[1]);
withWrap.Dump("Object {...} wrapped in JsonResponse: {Perf: {...}}");
noWrap.Dump("Object {...} not wrapped");
}
// You can define other methods, fields, classes and namespaces here
public string[] GetResp(){
string[] responses = {"""
{"Perf":{"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}}
""",
"""
{"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}
"""};
return responses;
}
public class JsonResponse{
public Perf Perf {get; set;}
}
public class PerfTest{
public string? Unit {get; set;}
public double? Value {get; set;}
}
public class Perf{
[Newtonsoft.Json.JsonProperty("perfRef")]
public string PerfRef { get; set; }
//public PerfRef perfRef { get; set; }
[Newtonsoft.Json.JsonProperty("perfTest")]
public PerfTest PerfTest { get; set; }
}
The result of the deserialized object JsonResponse and Perf are on the right side.

Unable to Deserialize Json to a class of same contract

I have the following class structure. If I use the same assembly of contracts (assembly with all data classes n other stuff) used by api, I am unable to deserialize it in my application.
But I need to remove the dependency of that assembly. So I created another assembly with same namespace and contracts.
Example: I have many parts, and I can have a car out of those parts or a motorcycle.
public class Car
{
public string Name {get; set;}
public Dictionary<string,Part> SpareParts {get; set;}
}
public class Part
{
public string PartName {get; set;}
public object Value {get;set;}
public string Type {get;set}
}
Now, I have a Generic Query request and response
public class QueryRequest
{
//Stuff.. Request works fine.. i get a response
}
public class QueryResponse
{
public QueryResult[] Result;
}
public classs QueryResult
{
//Other details like entity name n stuff for car or motorcycle etc.
public Part[] Parts;
}
Remember that Part Class with Value field, that contains List
It goes like this
public class abstract Spoke
{
}
public class Spoke1 : Spoke
{
}
public class Spoke2 : Spoke
{
}
In my response I get this weird serialized string
"Value": {
"$type": "System.Collections.Generic.List`1[[namespace.Spoke, namespace]], mscorlib",
"$values": [
{
"$type": "namespace.spoke2, namespace",
//Other Properties of spoke2
}]
}
EDIT: I get the data in format of QueryResponse which contains QueryResult n Parts
I m using Newtonsoft.Json, Any ideas how to deserialize that into my namespace2.Spoke
I have the whole contract copied in another assembly.
I have tried changing the namespace same as in response but doesn't work.
Any suggestions of help please.

How to make a right DTO class for request XML body on consuming Web API service

I am using RestSharp with C# codes to PUT data object (my_object) for a WEB API service operation that supports only XML format.
My question:
How can I make a right DTO class (e.g. Analytics, please see below) such that on calling request.AddBody(my_object) method of RestSharp, RestSharp is able to convert a data piece Timestamp to XML attribute along with other properties of Analytics DTO class?
my_object in method call request.AddBody(my_object) is custom AnalyticsLogs DTO class (please see below).
The following is an example request Xml body the Web API service operation requires:
<AnalyticsLogs>
<Analytics Timestamp="1999-05-31T11:20:00">
<UserExpId>9223372036854775807</UserExpId>
<UserExpStatus>String content</UserExpStatus>
<Category>String content</Category>
<Value>2147483647</Value>
</Analytics>
<Analytics Timestamp="2007-05-12T11:20:00">
<UserExpId>8223372036854775899</UserExpId>
<UserExpStatus>String content</UserExpStatus>
<Category>String content</Category>
<Value>2147483647</Value>
</Analytics>
</AnalyticsLogs>
I am planning to make some custom DTO classes like below. But for custom Analytics DTO class, I do not know how to make Timestamp data as an XML attribute according to the above request Xml body. Please advice.
public class AnalyticsLogs : List ;
public class Analytics
{
public long UserExpId { get;set;}
public string UserExpStatus { get; set;}
public string Category { get;set;}
public int Value {get; set;}
// how can I do for XML attribute Timestamp ??? It seems it can not a class property but I am not sure.
???
}
Thank you.
XmlAttribte #msdn
public class Analytics
{
public long UserExpId { get;set;}
public string UserExpStatus { get; set;}
public string Category { get;set;}
public int Value {get; set;}
[XmlAttribute]
public DateTime Timestamp { get; set; }
}
For RestSharp you use attribute SerializeAsAttribute. This is defined here.
public class Analytics
{
public long UserExpId { get;set;}
public string UserExpStatus { get; set;}
public string Category { get;set;}
public int Value {get; set;}
[SerializeAsAttribute]
public DateTime Timestamp { get; set; }
}

C# Serialize JSON object within JSON objects

I have these entities:
public class Product
{
public string Code {get;set;}
public string Name {get;set;}
public ICollection<Pack> Packs {get;set;}
}
public class Pack
{
public string Colour {get;set;}
public string Moq {get;set;}
}
my json object:
var products = [{
code: 1243123,
name: "Gel",
packs: [{
color: "blue",
moq: 10
}]
}];
note the naming differences, i.e. case and american spelling of color. Will the JavaScriptConvert.DeserializeObject() deserialise that correctly?
Or will I have to do it another way?
If I can just have an object where I can access those names directly and there values that would be great!
If you use something like JSON.NET, then you can use attributes to control serialization, such as:
public class Pack
{
[JsonProperty("color")]
public string Colour {get;set;}
[JsonProperty("moq")]
public string Moq {get;set;}
}
Also, given your expected output, your Product class should look like this I think:
public class Product
{
[JsonProperty("code")]
public long Code {get;set;}
[JsonProperty("name")]
public string Name {get;set;}
[JsonProperty("packs")]
public Pack[] Packs {get;set;}
}
Note Code and Packs type.
If you use DataContractJsonSerializer instead, you can put attributes to your properties, giving them different names in generated/parsed JSON:
[DataContract]
public class Pack
{
[DataMember(Name = "color")]
public string Colour {get;set;}
[DataMember(Name = "moq")]
public string Moq {get;set;}
}

How to mark up C# class with attributes to make it XML serializable?

So I have a class. I want to make it serializable (into XML and back). I know how to use Xml.Linq to serialize.. but it is serialization via hand - not automated alike protobuf with its [ProtoContract] and other attributes when I mark up class and get it back and forward serializable.
So I wonder ho waving
public class Entries {
public List<Entry> Entries {get; set;}
}
public class Entry {
public string Id {get; set;}
public string Path {get; set;}
}
get XML like:
<entries>
<entry id="value" path="value"/>
</entries>
So how to mark up C# class with attributes to make it XML serializable?
You need to use attributes like [XmlRoot] and [XmlAttribute] for this. You can specify the XML element names as a parameter on the attributes.
See http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute.aspx and the rest of the attributes in the namespace for the attributes you can use.
You need to add attributes to the class and class members that match your XML, for example: -
[Serializable]
[XmlRoot("RootNode")]
public class Example
{
[XmlElement("Foo")]
public string Foo { get; set; }
[XmlElement("Bar")]
public string Bar { get; set; }
}

Categories

Resources