Newtonsoft DeserializeObject not calling constructor - c#

I am having an issue with deserializing decimal value correctly. A suggestion on the site was to use a constructor but it is not calling that constructor.
Here is the JSON:
{
"errors": false,
"response": {
"entities": [
{
"currency_id": "1",
"balance": 1e-8,
"address": ""
},
{
"currency_id": "2",
"balance": 0,
"address": null
},
{
"currency_id": "3",
"balance": 0.09865566,
"address": null
},
{
"currency_id": "5",
"balance": 0,
"address": null
},
{
"currency_id": "6",
"balance": 0,
"address": null
}]
},
"pagination": {
"items_per_page": 100,
"total_items": 5,
"current_page": 1,
"total_pages": 1
}
}
My classes:
public class ApiResponse<T> where T : class
{
public bool Errors { get; set; }
public T Response { get; set; }
}
public class ApiPagingResponse<T> : ApiResponse<T> where T : class
{
public Pagination Pagination { get; set; }
}
public class GetBalanceListResponse
{
public GetBalanceListResponseEntity Entity { get; set; }
}
[JsonObject]
public class GetBalanceListResponseEntity
{
[JsonConstructor]
public GetBalanceListResponseEntity([JsonProperty("currency_id")]string currencyId, [JsonProperty("balance")]string balance, [JsonProperty("address")]string address)
{
CurrencyId = currencyId;
Balance = decimal.Parse(balance, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint,
CultureInfo.InvariantCulture);
Address = address;
}
[JsonProperty("currency_id")]
public string CurrencyId { get; set; }
[JsonProperty("balance")]
public decimal Balance { get; set; }
[JsonProperty("address")]
public string Address { get; set; }
}
I call it using this:
var result = JsonConvert.DeserializeObject<ApiPagingResponse<GetBalanceListResponse>>(stringResult);
Where stringResult is the json string I want to deserizalize.
Currently it just returns null for the Entity property of the response. All my other serialization works fine with this method, the problem is with "balance": 1e-8,
Has anyone dealt with a similar issue and can be of assistance with this?

Your use of [JsonConstructor] is correct. Your only problem is that, in GetBalanceListResponse, the method
public GetBalanceListResponseEntity Entity { get; set; }
should be
public List<GetBalanceListResponseEntity> Entities { get; set; }
This is because, in the JSON, the corresponding property response.entities is an array:
{
"errors": false,
"response": {
"entities": [
// Entity values omitted
]
},
// Pagination omitted
}
With this fix, the constructor is called and your code basically works. Sample fiddle.
To avoid this sort of problem in the future, you could use an automatic code-generation tool such as http://json2csharp.com/, Paste JSON as Classes or https://jsonutils.com/ to generate appropriate classes from your JSON, then modify as required, e.g. by making the auto-generated types generic.

Related

Nested item in json array is not being deserialized

I am trying to deserialize a json string from an api.
All works except for a nested item - Location which always ends up null
This is the string structure:
[
{
"CompanyProfile": "<p>A&B Inc etc...</p>",
"Address": "56 Test Street, Test, UK",
"Location": {
"Latitude": 61.52787,
"Longitude": -4.32095,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "A&B Inc"
},
{
"CompanyProfile": "<p>B&C Inc etc...</p>",
"Address": "57 Test Street, Test, UK",
"Location": {
"Latitude": 61.2122,
"Longitude": -4.31111,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "B&C Inc"
},
]
These are the classes to map to:
public class MemberDto
{
public int Id { get; set; }
public string? Name { get; set; }
public string? CompanyProfile { get; set; }
public string? Address { get; set; }
public Location? Location { get; internal set; }
}
public class Location
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
}
This is the deserialize code:
var result = await response.Content.ReadAsStringAsync();
var members = JsonConvert.DeserializeObject<List<MemberDto>>(result);
I know I can use ReadFromJsonAsync<List<MemberDto>>() as well but using ReadFromString so I can check the json before deserializing. Anyway the result is exactly the same for ReadFromJsonAsync.
Everything except Location is deserialized successfully
Anyone know what the issue is?
Remove the internal access modifier in the setter of Location.
public Location? Location { get; set; }

Deserializing JSON Class with multiple Objects with different types

I am trying to deserialize the following string output to json in csharp.
Now the Problem is, that there are multiple objects that i dont know how to access.
My endgoal would be to access for example just the twitch object.
How would my Jsonclass need to look like?
Thanks in advance.
[
{
"type": "battlenet",
"id": "zzzz#25589",
"name": "zzzz#25589",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "steam",
"id": "45356364364564",
"name": "zzzz",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "twitch",
"id": "4353454353453",
"name": "zzzzz",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "youtube",
"id": "xxxxx-xxxxxx",
"name": "Salt",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
}
]
What you have here is a JSON array of objects. You have to parse it to an array or List :
Your object :
public class SomeObject
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("visibility")]
public int Visibility { get; set; }
[JsonProperty("friend_sync")]
public bool FriendSync { get; set; }
[JsonProperty("show_activity")]
public bool ShowActivity { get; set; }
[JsonProperty("verified")]
public bool Verified { get; set; }
}
Parsing :
var resultList = JsonConvert.DeserializeObject<List<SomeObject>>(jsonstring);
Then, just search for the twitch object :
resultList.FirstOrDefault(x=>x.type == "twitch")
Maybe I'm on the wrong path right now,
but since they've got all the same attributes why don't you try implement an Interface/Superclass and use Reflection to get the correct Type according to the value in "type" ?
To get the instance:
public object GetInstance(string typeString)
{
Type t = Type.GetType(typeString);
return Activator.CreateInstance(t);
}

Not getting result when deserializing json using DataContractJsonSerializer

I have following json:
{
"Australia": {
"count": 2,
"records": {
"File1.ppt": {
"id": "123456789"
},
"File2.doc": {
"id": "987654321"
}
}
},
"PDFs.zip": {
"count": 0,
"records": {}
},
"Peru": {
"count": 2,
"records": {
"File3.PPT": {
"id": "897456123"
},
"File4.PPT": {
"id": "123546789"
}
}
},
"total count": 4
}
and to deserialize the above json I have defined some classes so that I can use these classes while deserializing my json into objects and below are the classes:
namespace GEO_Batch_Creation
{
[DataContract]
class BhpIdJson
{
[DataMember(Name = "objects")]
public Dictionary<string, Country[]> Countries { get; set; }
[DataMember(Name = "total count")]
public int TotalCount { get; set; }
}
[DataContract]
class Country
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "records")]
public Dictionary<string, Record> Records { get; set; }
}
[DataContract]
class Record
{
[DataMember(Name = "filename")]
public string FileName { get; set; }
[DataMember(Name = "id")]
public Dictionary<string, string> BhpId { get; set; }
}
}
But when I use following code to deserialize the json I am getting only total count.
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BhpIdJson));
BhpIdJson bsObj2 = (BhpIdJson)deserializer.ReadObject(ms);
}
Please suggest me where I am doing mistake.
I don't think that this JSON is in correct format. I don't know if you got this from somewhere or made for yourself, but if the last one I recommend you to change the structure.
Even in C# you cant realy create a class that has the objects and the count of the object in the same List or Array etc.
Based on your class your JSON yhould look like this:
{
"objects": [
{
"name": "Australia",
"count": 2,
"records": [
{
"fileName": "File1.ppt",
"id": "123456789"
},
{
"fileName": "File2.doc",
"id": "987654321"
}
]
}
],
"total count": 4
}
As you can see you have to add Name or something to your Country class. I hope it helped.
Edit:
You can create a list like I mentioned above but it's not a good practice I think.

JsonConvert.DeserializeObject Error reading object reference '1'

I am trying to deserialize an object in a Web Api from an object posted by angular. I am receiving an error: Error reading object reference '1'. Path 'Developers[0].DeveloperId', line 20, position 21
My Json object is (which has been validated as valid JSON):
{
"Id": 0,
"Name": "Name",
"OwnerId": 1,
"Description": "Description",
"Note": "My Notes",
"Stakeholders": [
{
"$id": "1",
"StakeholderId": 1,
"Name": "Mary",
"DateModified": "2018-02-21T12:28:15.023",
"DateCreated": "2018-02-21T12:28:15.023",
"$$hashKey": "object:3"
}
],
"Developers": [
{
"$id": "1",
"DeveloperId": 1,
"DeveloperName": "Joseph",
"DateModified": "2018-02-21T12:28:26.07",
"DateCreated": "2018-02-21T12:28:26.07",
"$$hashKey": "object:4"
}
]
}
I am trying to deserialize with:
var app = JsonConvert.DeserializeObject<Application>(request.ToString(), new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
The developer class (which is similar to Stakeholder class)
public class Developer : IModificationHistory
{
public int DeveloperId { get; set; }
[Required]
public string DeveloperName { get; set; }
[JsonIgnore]
public virtual List<Application> Applications { get; set; }
public DateTime DateModified { get; set; }
public DateTime DateCreated { get; set; }
}
The application class is simply:
public class Application
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public string Note { get; set; }
public virtual List<Stakeholder> Stakeholders { get; set; }
public int OwnerId { get; set; }
public virtual List<Developer> Developers { get; set; }
}
The javascript I use to call this post is:
var data =
{
Id: vm.appId,
Name: vm.applicationName,
OwnerId: vm.owner.DeveloperId,
Description: vm.applicationDescription,
Note: vm.note,
Stakeholders: vm.selectedStakeholders,
Developers: vm.selectedDevelopers
};
$http.post("/api/Application/Post/", JSON.stringify(data))
The Stakeholders List gets filled properly, but the Developers list does not. If I put developers in the list before stakeholders, then developers list gets filled properly and stakeholders does not. Any suggestions would be greatly appreciated!
The problem is with the same value of $id, both are set to 1, see inner exception:
{"A different value already has the Id '1'."}
I just changed its value to 2 and it is working fine:
{
"Id": 0,
"Name": "Name",
"OwnerId": 1,
"Description": "Description",
"Note": "My Notes",
"Stakeholders": [
{
"$id": "1",
"StakeholderId": 1,
"Name": "Mary",
"DateModified": "2018-02-21T12:28:15.023",
"DateCreated": "2018-02-21T12:28:15.023",
"$$hashKey": "object:3"
}
],
"Developers": [
{
"$id": "2",
"DeveloperId": 1,
"DeveloperName": "Joseph",
"DateModified": "2018-02-21T12:28:26.07",
"DateCreated": "2018-02-21T12:28:26.07",
"$$hashKey": "object:4"
}
]
}
Here is the screenshot of my output:

How to deserialize json string in windows phone?

I just got my json response as a string.My json is given below,
"code": 0,
"message": "success",
"students": {
"details":{
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}
}
}
Like hjeke and Second there are many key value pairs,how can i deserialize my json using Newtonsoft.json
Try to understand my solution in your previous question
How to deserialize json data in windows phone?
Your first JSON in that question was good and simple to use.
JSON, where field names are unique not convinient to deserialize. So, you got problems such as public class Hjeke and public class Second for each instance, when you use code generator.
Use JSON-structure with list of students:
"code": 0,
"message": "success",
"students": [
{
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
{
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}]
is good and flexible structure. Using this, you don't need to parse not obvious fields like
"details":{
"hjeke": {
and so on.
And work with them using classes, from my previous answer. The main idea - you need list of objects. public List<StudentDetails> students. Then, all students objects deserialized in List, which is easy to use.
As everybody mentioned your json seems to be very unflexible, huh.
You can extract the data you are interested in.
So this is your model:
public class StudentDetails
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
And this is how you can extract it:
var jsonObj = JObject.Parse(str);
// get JSON result objects into a list
var results = jsonObj["students"]["details"].Children().Values();
// serialize JSON results into .NET objects
var details = new List<StudentDetails>();
foreach (JToken result in results)
{
var st = result.ToString();
var searchResult = JsonConvert.DeserializeObject<StudentDetails>(st);
details.Add(searchResult);
}
I'm using a newtonsoft.json library here.
Your Response string has some mistakes man, its not a valid json
just small modification to be done as below:
{
"code": 0,
"message": "success",
"students": {
"details": {
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good"
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad"
}
}
}
}
you can make out the difference
Now Follow these steps:
1.Go to this link Json to C#
2.place your Json string there and generate C# class object
3.Now create this class in your solution
4.Now deserialize As below
var DeserialisedObject = JsonConvert.DeserializeObject<Your Class>(YourJsonString);
First, create the classes:
public class Hjeke
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Second
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Details
{
public List<Hjeke> hjeke { get; set; }
public List<Second> Second { get; set; }
}
public class Students
{
public List<Details> details { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string message { get; set; }
public List<Students> students { get; set; }
}
After that, use JSON.NET to deserialize:
var deserialized = JsonConvert.DeserializeObject<Class1>(YourStringHere);
Do you have any influence over the json response? Details should probably be a JSONArray in this case, not an object with a varying amount of properties, since I assume that's what you mean is the issue here.

Categories