RestSharp Deserialization with JSON Array - c#

I have a JSON response that I'm trying to deserialize with RestSharp, and it looks like this:
{"devices":[{"device":{"id":7,"deviceid":"abc123","name":"Name"}},
{"device":{"id":1,"deviceid":"def456","name":"Name"}}],
"total":2,
"start":0,
"count":2}
Based off of some suggestions I've found, I've tried to setup my POCO like this:
public class DevicesList
{
public List<DeviceContainer> Devices;
}
public class DeviceContainer
{
public Device Device;
}
public class Device
{
public int Id { get; set; }
public string DeviceId { get; set; }
public string Name { get; set; }
}
And then my execution looks like this:
// execute the request
var response = client.Execute<DevicesList>(request);
However, response.Data is NULL, and I've tried other variations with no luck.
So, what class structure and mapping should be used for this situation? I've also tried this without the extra DeviceContainer class.
Thanks for the help.

I had a slightly different issue when my deserialization POCO contained an array..
Changing it from Devices[] to List<Devices> resolved the issue and it deserialized correctly.

RestSharp only operates on properties, it does not deserialize to fields, so make sure to convert your Devices and Device fields to properties.
Also, double check the Content-Type of the response, if the responses is something non-default, RestSharp may not uses the JsonDeserializer at all. See my answer on RestSharp client returns all properties as null when deserializing JSON response

Something that I ran into is, it does not work if your using interfaces like: IEnumerable or IList, it has to be a concrete type.
This will not work, where as it does for some other json serializers like json.net.
public class DevicesList
{
public IEnumerable<DeviceContainer> Devices { get; set; }
}
public class DeviceContainer
{
...
}
it would have to be something like this:
public class DevicesList
{
public List<DeviceContainer> Devices { get; set; }
}
public class DeviceContainer
{
...
}

RestShartp doesn't support DataAnnotation/DataMember, rename your properties with no maj:
Devices -> devices
Device -> device
AND don't forget the {get; set;} ;).

My problem was entirely different, I naively thought JsonDeserializer supports JsonProperty attribute, but thats not true. So when trying to deserialize into
public class AvailableUserDatasApi
{
[JsonProperty("available-user-data")]
public List<AvailableUserDataApi> AvailableUserDatas { get; set; }
}
it failed.. But changing AvailableUserDatas to AvailableUserData was enough for things to start working.

Related

Deserialize first property not matching any target object's properties into specific property [duplicate]

This question already has answers here:
Deserialize json with known and unknown fields
(5 answers)
Closed 6 years ago.
I'm doing some web API integration with Newtonsoft.Json, and as always, I have to do dumb stunts to properly deserialize what they're sending back.
In this case, the API will send responses resembling this kind of structure:
{ "contacts": [ ... ], "has-more": true, "offset": 38817 }
The "has-more" and "offset" properties are pretty much constant on the different method responses, and have been defined accordingly on the response object that I'm deserializing into. The response object looks something like this:
public class APIResponse {
public JContainer Result { get; set; }
[JsonProperty("has-more")]
public bool HasMore { get; set; }
[JsonProperty("offset")]
public int Offset { get; set; }
}
That first "contacts" property is what can vary; for some methods, I might get "contacts", some might get "companies", and others might get who-knows-what. I also don't have any way to be certain that every response will have such a "variable" property, nor that it will be the first one, positionally speaking.
For this example, what I would like to happen is the deserializer looks at the Json and says, "Let's see, I don't see anything mapping to 'contacts', so we'll put that into 'Result', and then I can see from the JsonProperty attributes that 'has-more' and 'offset' go into HasMore and Offset. Okay, all set, here's your object."
I suspect this involves some tricks with a custom JsonConverter or IContractResolver, but I'm just not connecting the dots here. I tried doing a simple custom contract resolver, but it appears to use contract resolvers to resolve object property names into property names to look for in the JSON text, not vice-versa.
You can use a base class + derivations for each response type.
public class APIResponseBase {
[JsonProperty("has-more")]
public bool HasMore { get; set; }
[JsonProperty("offset")]
public int Offset { get; set; }
}
public class ContactsResponse : APIResponseBase {
public IEnumerable<Contact> Contacts { get; set; }
}
public class CompaniesResponse : APIResponseBase {
public IEnumerable<Company> Companies { get; set; }
}
var contactsResponse = JsonConvert.Deserialize<ContactsResponse>(json);
IEnumerable<Contact> contacts = contactsResponse.Contacts

Giant Bomb API Json

I'm trying to use the Giant Bomb API. I also use Newtonsoft.Json to deserialize the response object. I've a problem when I try to convert the response to classes. I've a problem with something who looks like an array. I don't understand what it exactly is and which using ref i should use to make it work ...
Here is the syntax : public ApiSearchResult[] results { get; set; }
Here is the tutorial : http://social.technet.microsoft.com/wiki/contents/articles/26920.winrt-using-giant-bomb-api-to-get-games-information.aspx
After looking at the documentation, it appears that ApiSearchResult is supposed to be Result. Try changing public ApiSearchResult[] results { get; set; } to
public Result[] results { get; set; }.

How to ignore data in JSON.NET that changes between returns

I'm parsing JSON data return by a third party.
I have my class generated with JSON2CSharp which works for the first sample we received. I tweaked it to have some JsonProperty settings so that it doesn't require certain properties that are not always present.
Now I received more samples and one of the datablobs changed format
from needing
public Translations Translations { get; set; }
to
public List<Translations> Translations { get; set; }
The blob however is information we do not need, for both performance and not having to deal with that and other pieces of information we do not need changing format, it would be ideal to just ignore it when deserializing it.
Now the real question is, should "JsonIgnore" just ignore the entire blob of data irregardless if it is in a different format then defined in the class? Or do I have to program around that?
So if I do
[JsonIgnore]
public string Translations { get; set; }
will it also ignore Translations when it gets sent a list or an object?
Can I use the same syntax with JsonIgnore as I can with JsonProperty and just say
[JsonIgnore(PropertyName = "translations")]
or does JsonIgnore just toss out anything it receives?
Additionally question:
Is it convention that when there are no translations, I get:
"translations":[]
and when there are translations I get:
"translations":{"CA":"blabla","DD":"C : blablah"}
Or is this likely a bug in the third party's website?
ADDED:
1: The Translations can switch between string, list and object between every fetch of the JSON.
2: For using DataMembers ignoring everything I don't actually need, in a class with subclasses, do I have to tell it that the subclass is [DataMember] or the subclasses properties are [DataMember]?
I would explicitly specify exactly the properties I wanted serialized/deserialized in my data class using DataContractAttribute and DataMemberAttributes for the members you actually want to deserialize.
This is opt in, so no attempt is made to shoehorn anything extra in your JSON into your data class, and anything extra in your data class doesn't show up in serialized JSON.
So assuming your class right now looks like this:
class MyData {
// Old member
// public Translations Translations { get; set; }
public List<Translation> Translations { get; set; }
public string ThisShouldBeSerialized { get; set; }
}
You can change it so things that you want serialized are explicitly marked as such, and anything not marked for serialization is ignored by default:
[DataContract]
class MyData {
// Old member
// public Translations Translations { get; set; }
public List<Translation> Translations { get; set; }
[DataMember]
public string ThisShouldBeSerialized { get; set; }
}
And then:
var myJSON = #"{
'ThisShouldBeSerialized': 'test',
'Translations': {
'Some' : 'Strange',
'Data' : 'Blob'
}
}";
var result = JsonConvert.DeserializeObject<MyData>(myJSON);

How to XmlDeserialize using RestSharp?

I'm having trouble deserializing the following XML w/ restsharp
<Xid>
<Id>118</Id>
<Active>true</Active>
<Xid>20</Xid>
<CreatedDate>2011-09-16T18:15:32</CreatedDate>
<CreatedUserId>1782</CreatedUserId>
<ModifiedDate>2011-09-16T18:15:32</ModifiedDate>
<ModifiedUserId>1782</ModifiedUserId>
<TableName>ProjectRate</TableName>
<ObjectId>644</ObjectId>
<SystemGuid>157f2e2d-5e8b-41c7-b932-09c1d75d0ccc</SystemGuid>
</Xid>
I can't use a class named 'Xid' with a member named 'Xid' as there is a conflict in C#. I have tried manually declaring the XmlRoot on the XidClass object, but it doesn't seem to be getting picked up by RestSharp's deserializer. Is there a way to do this with RestSharp, or am I going to need to write a custome deserializer for this particular chunk of xml?
You need to create the class by hand, befoe you can deserialize the XML:
public class Xid
{
public int Id { get; set; }
public bool Active { get; set; }
public int Xid { get; set; }
...
}
The you should be able to deserialize using something like:
Xid xid = xml.Deserialize<Xid>(response);
(Have a look here: Testing the Deserialization of RestSharp without proper REST-Api)

custom Serialize Class to JSon - for really small data

well,
i have a really simple class:
public class Channel : IContent
{
public Guid Guid { get; set; }
public string Title { get; set; }
public string Alias { get; set; }
public void Set()
{
// SAVE JSON DATA
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(string.Join("", this.Guid, ".jsv")))
{
writer.Write("{ \"Title\":", this.Title, "}");
}
}
}
Serializing i could do as shown in code,
but how can i load that back into the class? that is the actual question.
please dont refer me to JavaScriptSerializer or DataContracts etc...
again, this should be so simple... that i dont think i need all those.
Json.NET. No, seriously you need a JSON serializer. Just pick one that you like. The 3 that have been listed work great. And make sure you read this article to better understand why you need a JSON serializer.

Categories

Resources