Newtonsoft.DeserializeObject for generic class - json

I have a JSON response like the following
{
"msg": "1",
"code": "2",
"data": [
{
"a": "3",
"b": "4"
}
],
"ts": "5"
}
I would like to create a generic class
public class DTWSResponse<T>
{
public string msg { get; set; }
public string code { get; set; }
public T data { get; set; }
public long ts { get; set; }
}
so this class will map each of the variable. But the data portion can be generic, i.e. it might have different format rather than 2 variables a and b.
So I create another class
public class DTProf
{
public string a { get; set; }
public string b { get; set; }
}
and in my code, I call as
DTWSResponse<DTProf> prof = JsonConvert.DeserializeObject<DTWSResponse<DTProf>>(json);
But I'm getting the following error
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'DataTransfer.DTProfile' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'data', line 1, position 40.
Any ideas?

Use the correct type for the generic type argument
the JSON shown has a collection for the data property. So use a collection as the type argument. No need to change the generic class.
var prof = JsonConvert.DeserializeObject<DTWSResponse<IList<DTProf>>>(json);
var a = prof.data[0].a;

Make data a generic list and you should be fine...
public class DTWSResponse<T>
{
public string msg { get; set; }
public string code { get; set; }
public IList<T> data { get; set; }
public long ts { get; set; }
}

Related

An error occurred while deserializing the type 'newtonsoft.json.linq.jtoken' does not have a suitable constructor or add method

I am trying to list my data from my mongodb database but while calling the method this exception is appearing.
I'm getting following exceptions:
An error occurred while deserializing the Value property of class ExampleClass: Type 'Newtonsoft.Json.Linq.JToken' does not have a suitable constructor or Add method.
MongoDB.Bson.BsonSerializationException: Type 'Newtonsoft.Json.Linq.JToken' does not have a suitable constructor or Add method.
And it looks like the issue happens when it tries to read an entry from MongoDB, which has this "Value" key:
"Value": {
"_t": "Newtonsoft.Json.Linq.JArray, Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed",
"_v": [{
"_t": "JValue",
"_v": []
}, {
"_t": "JValue",
"_v": []
}]
}
This is my class:
public class Customer
{
[MongoDB.Bson.Serialization.Attributes.BsonId]
[MongoDB.Bson.Serialization.Attributes.BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[MongoDB.Bson.Serialization.Attributes.BsonRepresentation(BsonType.ObjectId)]
public string FacilityID { get; set; }
[MongoDB.Bson.Serialization.Attributes.BsonElement]
public string Name { get; set; }
[MongoDB.Bson.Serialization.Attributes.BsonElement]
public string Definition { get; set; }
[ArrayOfArrays]
public Dictionary<CustomField,object> CustomFields {get;set;}
}
The problem is caused by these CustomFields. CustomField is actually an enum, I ran into this problem when I replaced an object with a class. How should I change the class structure?
CustomFields.Add(CustomField.Name,ExampleClass);

Cannot Get JsonConvert.DeserializeObject with oData to Work

I a class that looks like so:
public class AccountAddress
{
[Key]
public int accountNumber { get; set; }
public int rowNumber { get; set; }
public string civicaddress { get; set; }
public AccountAddress()
{
//Default constructor
}
}
There is a rest API that returns a List of AccountAddress as oData that looks like this to a variable "result":
{
"#odata.context":"http://localhost:52139/odata/$metadata#WEB_V_CIVIC_ADDRESS/Values.Classes.Entities.AccountAddress","value":[
{
"#odata.type":"#Values.Classes.Entities.AccountAddress","accountNumber":123456,"rowNumber":0,"civicaddress":"123 FAKE EAST DRIVE"
},{
"#odata.type":"#Values.Classes.Entities.AccountAddress","accountNumber":123457,"rowNumber":0,"civicaddress":"123 FAKE WEST DRIVE"
}
]
}
When I try to use:
var addressAccountLookup = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AccountAddress>>(result);
I get an error
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ATPublicTAX.Regina.ca.Values.Classes.Entities.AccountAddress]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Any help on this would be greatly appreciated.
Thanks.
You're passing the entire object to your deserialization method. You need to pass only the array, which is what it's asking you to do.
JArray array = (JArray) result["value"];
var addressAccountLookup = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AccountAddress>>(array);
Something like that should work.
The solution that I got to work is create a class:
private class oDataResponse<T>
{
public List<T> Value { get; set; }
}
Then deserialize like this:
var oDataRespone = Newtonsoft.Json.JsonConvert.DeserializeObject<oDataResponse<AccountAddress>>(result);

How do I deserialise json to c# that is valid json but doesn't follow a standard object pattern as it has no base parameter pair

I have the following JSON:
[{
"theme-my-login":
{
"latest_version":"6.4.7",
"last_updated":"2017-01-06T18:14:00.000Z",
"popular":true,
"vulnerabilities":
[
{
"id":6043,
"title":"Theme My Login 6.3.9 - Local File Inclusion",
"created_at":"2014-08-01T10:58:35.000Z",
"updated_at":"2015-05-15T13:47:24.000Z",
"published_date":null,
"references":
{
"url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
},
"vuln_type":"LFI",
"fixed_in":"6.3.10"
}
]
}
},{
"other-item":
{
"latest_version":"6.4.7",
"last_updated":"2017-01-06T18:14:00.000Z",
"popular":true,
"vulnerabilities":
[
{
"id":6043,
"title":"Theme My Login 6.3.9 - Local File Inclusion",
"created_at":"2014-08-01T10:58:35.000Z",
"updated_at":"2015-05-15T13:47:24.000Z",
"published_date":null,
"references":
{
"url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
},
"vuln_type":"LFI",
"fixed_in":"6.3.10"
}
]
}
}]
json2csharp says the object model should look like this, but that's clearly not correct
public class References
{
public List<string> url { get; set; }
}
public class Vulnerability
{
public int id { get; set; }
public string title { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
public object published_date { get; set; }
public References references { get; set; }
public string vuln_type { get; set; }
public string fixed_in { get; set; }
}
public class ThemeMyLogin
{
public string latest_version { get; set; }
public DateTime last_updated { get; set; }
public bool popular { get; set; }
public List<Vulnerability> vulnerabilities { get; set; }
}
public class RootObject
{
public ThemeMyLogin __invalid_name__theme-my-login { get; set; }
}
that I am trying to deserialise into c# classes using Json.NET, but as the top level item doesn't have a traditional name:value pair (the name effectively is "theme-my-login" and the value is the object), it's not deserialising.
Any pointers on how I can get this to deserialise? Do I need to use a custom deserialiser?
The reason I cannot use a dictionary as suggested in How can I parse a JSON string that would cause illegal C# identifiers? is that I need the value "theme-my-login" as one of the values in my model as it defines the object. I have added a second item into the json as this will be a list of items. I previously only included one to show the item structure.
You need to deserialize to List<Dictionary<string, ThemeMyLogin>> like so:
var root = JsonConvert.DeserializeObject<List<Dictionary<string, ThemeMyLogin>>>(json);
The code-generation site http://json2csharp.com/ has some limitations of which you need to be aware:
The JSON standard allows for two types of container:
The array, which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
The object, which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).
If your root container is an array, http://json2csharp.com/ will auto-generate a RootObject model to deserialize each object in the array. To actually deserialize the entire array you need to deserialize to a collection of root objects such as a List<RootObject>. See Serialization Guide: IEnumerable, Lists, and Arrays.
When a JSON property corresponds to an invalid c# identifier, http://json2csharp.com/ will "helpfully" add a property to the containing type that looks like this:
public PropertyType __invalid_name__my-invalid-identifier { get; set; }
Of course this will not compile, so you need to notice any __invalid_name properties and manually fix the generated code. Options for doing this include those covered in How can I parse a JSON string that would cause illegal C# identifiers? and elsewhere:
If the property name is fixed and known in advance, rename the c# property to something valid consistent with your coding conventions and mark it with [JsonProperty("my-invalid-identifier")]. (From the answer by ken2k).
If the containing type consists entirely of variable property names with a fixed schema for their values corresponding to some type T, replace the containing type with a Dictionary<string, T>. (From the answer by L.B.)
If the containing object has a mixture of fixed and variable properties, see Deserialize json with known and unknown fields or How to deserialize a child object with dynamic (numeric) key names?.
You seem to have encountered both limitations. Working sample .Net fiddle.

Deserializing JSON with JSON.NET in Windows 8 Store App

I'm trying to deserialize the following JSON into an object in my Win 8 app:
{
"success":true,
"pharmacies":[
{
"name":"Test Pharmacy",
"phone":null,
"description":"sample description",
"pharmacyid":"1234567",
"pic":"/1341864197.png",
"address":"211 Warren St., #205",
"city":"Newark",
"state":"NJ",
"zipcode":"07103",
"delivery":true,
"dob_check":false,
"name_check":false,
"can_pickup":true,
"barcode_template":"9999999XX"
}
]
}
This is the model I'm using:
public class PharmacyList
{
public List<Pharmacy> pharmacies { get; set; }
}
public class Pharmacy
{
public string pharmacyid { get; set; }
public string name { get; set; }
public string phone { get; set; }
}
And here is the code I'm using to de-serialize
json = await results.Content.ReadAsStringAsync();
List<PharmacyList> p = JsonConvert.DeserializeObject<List<PharmacyList>>(json);
I'm getting the following exception:
: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[PharmacyHC.Models.PharmacyList]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Am I trying to deserialize into the wrong type or should I format the JSON as it comes back from the API differently?
I just realized the dumb mistake I made. p should have been declared as type PharmacyList instead of a list object since the class declaration for PharmacyList contained a List object already.
List<PharmacyList> p = JsonConvert.DeserializeObject<List<PharmacyList>>(json);
it should have been
PharmacyList p = JsonConvert.DeserializeObject<PharmacyList>(json);

How to replace $ when converting JSON object to c# with out actually changing the name of that particular field in which $ exists?

When I'm converting Json objects to c#, I got an issue In which my Json has fields with $ symbol(ex: $t).But c# doesn't accept fields with special characters. If i try to replace $ with any other letters in my c# code, I'm unable to get data from 3rd party because of the change in naming.
How can I solve this issue?
Json string:
"author": [(1)
{
"name": {
"$t": "theabctv"
},-
"uri": {
$t": "http://gdata.abc.com/feeds/api/users/theabctv"
},-
"yt$userId": {
"$t": "tCUABCCT7wYG1PMCpw"
}-
}-
],-
C# code:-
public class Author2
{
public Name2 name { get; set; }
public Uri2 uri { get; set; }
public YtUserId __invalid_name__yt$userId { get; set; }
}
public class Name2
{
public string __invalid_name__$t { get; set; }
}
public class Uri2
{
public string __invalid_name__$t { get; set; }
}
public class YtUserId
{
public string __invalid_name__$t { get; set; }
}
There is no way to declare property names with symbols in NET framework, meaning that you cant have isomorphism between the JSON objects and the C# objects without parsing the JSON data. You could replace all $ symbol with any given string (carefully chosen), manage the data in the code behind and when you need to send JSON data of the object apply the inverse replacement.