C# DataContract custom deserialisation - c#

I need help with a DataContract problem. I have a web service that outputs JSON that needs to map to a C# object.
The important data returned from the API is wrapped in a "data" key of the JSON object but this is not important to me and I would like to discard it and have the JSON deserialised into the Item class. The Item class is used elsewhere and I would really like to leave it unchanged if possible.
Is there a way to change how data from the JSON is deserialised into the Item object but leave the Item object serialisation as default?
Currently the code is doing var item = await response.Content.ReadAsAsync<Item>(); to build the object from the API response.
If its not possible to leave the Item class unchanged then can you suggest the easiest modification to achieve the goal.
JSON:
{
"data": {
"id": "13c38fe9-6d9f-4a11-8eda-d071f2a99698",
"item_type": 100,
"item_name": "My Item Name"
}
}
C# Object:
[DataContract]
public class Item
{
[DataMember(Name = "id")]
public Guid Id { get; set; }
[DataMember(Name = "item_type")]
public int? ItemType { get; set; }
[DataMember(Name = "item_name")]
public string ItemName { get; set; }
}
Any help would be greatly appreciated as C# is not normally a language I work with.

Based on your json, your data is coming in a format of a class like this
[DataContract]
public class Wrapper
{
[DataMember(Name = "data")]
public Item item { get; set; }
}
[DataContract]
public class Item
{
[DataMember(Name = "id")]
public Guid Id { get; set; }
[DataMember(Name = "item_type")]
public int? ItemType { get; set; }
[DataMember(Name = "item_name")]
public string ItemName { get; set; }
}
Your response is in the format of a wrapper where data is an property of type Item. Add a wrapper to your contracts, it should work fine.
You could run it like this, to check if your serialized string is in the same format.
Wrapper tempData = new Wrapper() { item = new Item() {
Id = new Guid("13c38fe9-6d9f-4a11-8eda-d071f2a99698"),
ItemName = "My Item Name",
ItemType = 100 } };
var serializedDta = JsonConvert.SerializeObject(tempData);

Related

Deserializing partial json content with RestSharp

I'm using RestSharp for making requests and deserializing responses into C# models with NewtonsoftJsonSerializer. And I ran into the situation where I am getting 2 similar json strings.
First:
{
"updated": "",
"data":{
"categories":[...],
"products": [...]
}
}
Second:
{
"updated": "",
"categories":[...],
"products": [...]
}
For deserializing the first one I'm using the following C# model:
public class Root
{
[JsonProperty("updated")] public string Updated{ get; set; }
[JsonProperty("data")] public Data Items{ get; set; }
}
public class Data
{
[JsonProperty("categories")] public List<Category> Categories { get; set; }
[JsonProperty("products")] public List<Dish> Products { get; set; }
}
public class Category{...}
public class Dish{...}
I now I can use Data class for deserializing the second json string. But I want to use one model for deserialising both of them. And deserializing first json into Data class obviously returns null. Basically I need only categories and products lists.
What should I change in my model to make it happen?
Is there any attribute that can help?
If you define class like this and deserialize json responses into this class, you can have a single class but some fields will be null for each different response.
public class Data
{
[JsonProperty("updated")] public string Updated{ get; set; }
[JsonProperty("categories")] public List<Category> Categories { get; set; }
[JsonProperty("products")] public List<Dish> Products { get; set; }
[JsonProperty("data")] public Data Items{ get; set; }
}
If you don't want to do it as above, I think you should create a custom deserializer as it is described here:
How to implement custom JsonConverter in JSON.NET?
try this
var jsonParsed = JObject.Parse(json);
Root data;
if (jsonParsed["data"] != null)
data = jsonParsed.ToObject<Root>();
else
{
data = new Root
{
Updated = (string)jsonParsed["updated"],
Items = new Data
{
Categories = jsonParsed["categories"].ToObject<List<Category>>(),
Products = jsonParsed["products"].ToObject<List<Dish>>()
}
};
}

Adding JArray to an existing property

I have this JSON:
{
"ID":123,
"Products":null,
"Title":"Products"
}
I want to add some data from DB to the "Products" node so my final json will look like so:
{
"ID":123,
"Products":[
{
"ID":1,
"Name":"AA"
},
{
"ID":2,
"Name":"BB"
}
],
"Title":"Products"
}
I'm using this code:
internal class Product
{
public int ID { get; set; }
public string Name { get; set; }
}
//simulate DB
var products= new List<Product>()
{
new Product() {ID=1,Name="AA" },
new Product() {ID=2,Name="BB" }
};
string JSONstr = FilesUtils.OpenFile(Path.Combine(Environment.CurrentDirectory, "Sample.json"));
JObject JSON = JObject.Parse(JSONstr);
((JValue)JSON["Products"]).Value = JObject.FromObject(products);
But I get an exception:
Object serialized to Array. JObject instance expected.
You can do:
JSON["Products"] = JToken.FromObject(products);
To add a new property, do the same thing, e.g.:
JSON["TimeStamp"] = JToken.FromObject(DateTime.UtcNow);
Notes:
The item setter for JObject will add or replace the property with the specified name "Products".
JToken.FromObject() serializes any .Net object to a LINQ to JSON hierarchy. JToken is the abstract base class of this hierarchy and so can represent both arrays, objects, and primitives. See here for details.
Sample fiddle.
The expected object will have to be (according to your JSON). If that's the JSON you want you might consider wrapping it up and adding the ID and a Title as shown in the JSON.
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
}
public class YourObject
{
public int ID { get; set; }
public List<Product> Products { get; set; }
public string Title { get; set; }
}

How to Convert Json Object to Array in C#

I am trying to convert a JSON object in to C# array.
this is the JSon I Getfrom the Server webrequest response:
string result = sr.ReadToEnd(); // this line get me response
result = {
"subjects": [{
"subject_id": 1,
"subject_name": "test 1",
"subject_class": 4,
"subject_year": "2015",
"subject_code": "t-1"
},{
"subject_id": 2,
"subject_name": "test 2",
"subject_class": 5,
"subject_year": "",
"subject_code": "t-2"
}]
};
dynamic item = JsonConvert.DeserializeObject<object>(result);
string iii = Convert.ToString(item["subjects"]);
I want to Get the Subjects and Save them in Array so i can use them for other purpose.
I use these to Method but always got the empty values.
List<subjects> subject1 = (List<subjects>)JsonConvert.DeserializeObject(iii, typeof(List<subjects>));
and
subjects[] subject2 = JsonConvert.DeserializeObject<subjects[]>(iii);
Please Help Me to Solve this.
And my Subject Class is..
class subjects
{
public int id { get; set; }
public string name { get; set; }
public int class_name { get; set; }
public string year { get; set; }
public string code { get; set; }
}
The property names won't match as is, because you subjects class don't have the 'subject_' prefix the JSON object has. Easiest fix is to change your property names as shown in Ali's answer. Just in case you need to keep your property names as is, you can also use a JsonProperty attribute to alter the serialization names (perhaps there's a more generic way using some sort of converter, but didn't think the amount of properties needed it)
class subjects
{
[JsonProperty("subject_id")]
public int id { get; set; }
[JsonProperty("subject_name")]
public string name { get; set; }
[JsonProperty("subject_class")]
public int class_name { get; set; }
[JsonProperty("subject_year")]
public string year { get; set; }
[JsonProperty("subject_code")]
public string code { get; set; }
}
If you never need the root subjects you can also skip it without dynamic or an extra class with something like:
subjects[] arr = JObject.Parse(result)["subjects"].ToObject<subjects[]>();
(JObject is part of the namespace Newtonsoft.Json.Linq )
You need to create a structure like this:
public class Subjects
{
public List<Subject> subjects {get;set;}
}
public class Subject
{
public string subject_id {get;set;}
public string subject_name {get;set;}
}
Then you should be able to do:
Subjects subjects = JsonConvert.DeserializeObject<Subject>(result);

JSON Serializing confusion

I'm simply building a test Web API that takes a JSON payload and will simply send back the data in the array portion from my MVC Controller.
This is my current JSON string when serialized by my populated classes:
{"JobList":[{"ID":1,"Name":"Dave","Age":23,"StartDate":"10/23/2013 6:22:50 AM","JobTitle":"Developer"},{"ID":2,"Name":"John","Age":44,"StartDate":"10/23/2013 6:22:50 AM","JobTitle":"QA"},{"ID":3,"Name":"Dave","Age":23,"StartDate":"10/23/2013 6:22:50 AM","JobTitle":"Senior Developer"}]}
This is the object used to create this JSON:
var jobList = new JobsList()
{
JobList = new List<Jobs>()
{
new Jobs()
{
Age = 23,
ID = 1,
Name = "Dave",
StartDate = DateTime.Now.ToString(),
JobTitle = "Developer"
},
new Jobs()
{
Age = 44,
ID = 2,
Name = "John",
StartDate = DateTime.Now.ToString(),
JobTitle = "QA"
},
new Jobs()
{
Age = 23,
ID = 3,
Name = "Dave",
StartDate = DateTime.Now.ToString(),
JobTitle = "Senior Developer"
}
}
};
Here are my individual classes:
JobsList Class:
public class JobsList:IJobList
{
#region IJobList Members
public List<Jobs> JobList
{
get;
set;
}
#endregion
}
Jobs Class:
public class Jobs:Interfaces.IJobs
{
#region IJobs Members
public int ID
{
get;
set;
}
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
public string StartDate
{
get;
set;
}
public string JobTitle
{
get;
set;
}
#endregion
}
When I convert my JSON to produce classes through the use of JSON2Csharp the classes are produced as shown:
public class JobList
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string StartDate { get; set; }
public string JobTitle { get; set; }
}
public class RootObject
{
public List<JobList> JobList { get; set; }
}
This to me seems incorrect. Can anyone explain why I am not getting a 'Jobs' node in my JSON set to the JobsList array? And why do the generated JSON2CSharp classes map my 'Jobs' class as a JobList class?
Basically, it's because deserializer (in this case, JSON2CSharp) doesn't know what you named your original classes. Or how you structured them, for that matter. It doesn't know about any of that stuff you posted below "my current JSON string."
When you hand it that JSON object, that's all the information it is working with. So, it can tell that there's some sort of object (which it calls "RootObject"), which has an array of objects called "JobList". So it called the class "JobList". It had a choice there -- it could have simply called the list "JobList" and named the object something else... but it has no way of knowing that it was originally from an object named "Jobs", because that's not in the JSON. A different deserializer may have done it differently.
I am not familiar with JSON2CSharp specifically, so I don't know if it can do this, but there are frameworks that, given the object definition, can parse a JSON string with consistently named fields and load it into that object. For example, with Json.NET, you can do something like this:
JobsList jobList = JsonConvert.DeserializeObject<JobsList>(JsonString);

Json.NET Serializing my object gives me the wrong output

I'm having a bit of a problem with serializing my .NET objects into JSON using JSON.NET. The output I want to be serialized will have to look like this:
{"members":[
{"member":
{
"id":"4282",
"status":"1931",
"aktiv":"1",
"firmanavn":"firmname1",
"firmaUrl":"www.firmurl.dk",
"firmaUrlAlternativ":"",
"firmaSidstKontrolleretDato":"30-08-2010",
"firmaGodkendelsesDato":"07-03-2002"
}
},
{"member":
{
"id":"4283",
"status":"1931",
"aktiv":"1",
"firmanavn":"firmname2",
"firmaUrl":"www.firmurl.dk",
"firmaUrlAlternativ":"",
"firmaSidstKontrolleretDato":"30-08-2010",
"firmaGodkendelsesDato":"18-12-2000"
}
},
...... long list of members omitted
My .NET structure for now (still experimenting to get the right output) is like this:
public class Members
{
public List<Member> MemberList { get; set; }
}
and:
public class Member
{
[JsonProperty(PropertyName = "Id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "Status")]
public string Status { get; set; }
[JsonProperty(PropertyName = "Aktiv")]
public string Aktiv { get; set; }
[JsonProperty(PropertyName = "Firmanavn")]
public string Firmanavn { get; set; }
[JsonProperty(PropertyName = "FirmaUrl")]
public string FirmaUrl { get; set; }
[JsonProperty(PropertyName = "AltFirmaUrl")]
public string AlternativFirmaUrl { get; set; }
[JsonProperty(PropertyName = "FirmaSidstKontrolleretDato")]
public string FirmaSidstKontrolleretDato { get; set; }
[JsonProperty(PropertyName = "FirmaGodkendelsesDato")]
public string FirmaGodkendelsesDato { get; set; }
}
What the above .NET structure gives me when calling:
string json = JsonConvert.SerializeObject(members, Newtonsoft.Json.Formatting.Indented);
Where 'members' is a list of members. Is this:
{
"Members": [
{
"Id": "1062",
"Status": "1933",
"Aktiv": "1",
"Firmanavn": "firmname",
"FirmaUrl": "http://www.firmurl.dk",
"AltFirmaUrl": "http://www.altfirmurl.dk",
"FirmaSidstKontrolleretDato": "13-09-2011",
"FirmaGodkendelsesDato": "13-09-2511"
},
{
"Id": "1060",
"Status": "1933",
"Aktiv": "1",
"Firmanavn": "firmname2",
"FirmaUrl": "http://www.firmurl.dk",
"AltFirmaUrl": "http://www.altfirmurldk",
"FirmaSidstKontrolleretDato": "13-09-2011",
"FirmaGodkendelsesDato": "13-09-2511"
},
So basically, the structure is right in that it creates the array of members as expected, but I am missing the "member": label on each of the member objects. Is there any way to make such a label? Some kind of class declaration, or something?
I hope my question is clear, if not - please let me know and I'll try to explain further.
Thanks a lot in advance.
/ Bo
It sounds like you just need to make an intermediary object with a property of that name to get the JSON you want; however, I'd consider using the JSON.net originally rendered JSON (as it is structurally better).

Categories