Deserializing Json with an index - c#

I try to deserialize a JSon answer from a webservice, but I don't know how do this.
There is an example :
{
"0": {
"course_info": {
"course_id": 3,
"code": "",
"course_name": "Fiches Docebo",
"course_description": "<p>Fiches pratiques Docebo<\/p>",
"status": "2",
"selling": "0",
"price": "",
"subscribe_method": "2",
"course_edition": "0",
"course_type": "elearning",
"sub_start_date": "",
"sub_end_date": "",
"date_begin": "0000-00-00",
"date_end": "0000-00-00",
"course_link": ""
}
},
"1": {
"course_info": {
"course_id": 5,
"code": "prout",
"course_name": "Prout",
"course_description": "<p style=\"text-align: justify;\">Prout<\/p>",
"status": "2",
"selling": "0",
"price": "",
"subscribe_method": "2",
"course_edition": "0",
"course_type": "elearning",
"sub_start_date": "",
"sub_end_date": "",
"date_begin": "0000-00-00",
"date_end": "0000-00-00",
"course_link": ""
}
},
"success": true
}
The first node is an index, and I don't succeed to deserialize this without declarate one by one numbers...
I try like this :
public class ListCoursesResponse
{
public bool? success { get; set; }
public Dictionary<String,Course> courses { get; set; }
}
but It doesn't work.
I don't know how explain to RestSharp first nodes are numbers which are 1, 2, 3 to the last node...
Maybe I need to code a specific deserializer, but I don't know how..
I'm using RestSharp deserializer.
EDIT : there is Course class
[DeserializeAs(Name = "course_info")]
public class Course
{
[DeserializeAs(Name = "course_id")]
public long? Id { get; set; }
[DeserializeAs(Name = "course_name")]
public string Name { get; set; }
public string Code { get; set; }
[DeserializeAs(Name = "course_description")]
public string Description { get; set; }
[DeserializeAs(Name = "course_edition")]
public Boolean? IsEditable { get; set; }
[DeserializeAs(Name = "course_link")]
public string Url { get; set; }
[DeserializeAs(Name = "course_type")]
public string Type { get; set; }
[DeserializeAs(Name = "date_begin")]
public string BeginDate { get; set; }
[DeserializeAs(Name = "date_end")]
public string EndDate { get; set; }
public string Price { get; set; }
[DeserializeAs(Name = "selling")]
public Boolean? IsSalable { get; set; }
public int? Status { get; set; }
[DeserializeAs(Name = "sub_start_date")]
public string SubscriptionStartDate { get; set; }
[DeserializeAs(Name = "sub_end_date")]
public string SubscriptionStopDate { get; set; }
[DeserializeAs(Name = "subscribe_method")]
public int? SubscriptionMethod { get; set; }
}
EDIT 2 : There is how I call the library
public ListCoursesResponse ListCourses(int? categoryId = null)
{
if (categoryId != null)
{
List<KeyValuePair<String, Object>> list = new List<KeyValuePair<string, object>>();
list.Add(new KeyValuePair<String, Object>("category", categoryId));
return Execute<ListCoursesResponse>(String.Format("{0}/{1}", _course, "listCourses"), list.ToArray());
}
return Execute<ListCoursesResponse>(String.Format("{0}/{1}", _course, "listCourses"));
}
public T Execute<T>(string resource, params KeyValuePair<String, Object>[] parameters) where T : new()
{
var client = new RestClient();
client.AddHandler("text/html", new RestSharp.Deserializers.JsonDeserializer());
client.BaseUrl = DoceboApiUrl;
var requestUrl = DoceboApiUrl;
if (!requestUrl.EndsWith("/"))
requestUrl += "/";
requestUrl += resource;
var req = new RestRequest(RestSharp.Method.POST);
req.Resource = resource;
// Parameters Management
if (parameters != null)
foreach (KeyValuePair<String, Object> kvp in parameters)
req.AddParameter(new Parameter() { Name = kvp.Key, Value = kvp.Value, Type = ParameterType.GetOrPost });
client.Authenticator = new DoceboAuthenticator(ApiKey, ApiSecret, req.Parameters);
var response = client.Execute<T>(req);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
throw new ApplicationException(message, response.ErrorException);
}
return response.Data;
}

Proxy classes (ListCoursesResponse is writed as you wanted, rest is generated from json with json2csharp.com):
public class ListCoursesResponse
{
public bool? success { get; set; }
public Dictionary<String, Course> courses { get; set; }
}
public class Course
{
public CourseInfo course_info { get; set; }
}
public class CourseInfo
{
public int course_id { get; set; }
public string code { get; set; }
public string course_name { get; set; }
public string course_description { get; set; }
public string status { get; set; }
public string selling { get; set; }
public string price { get; set; }
public string subscribe_method { get; set; }
public string course_edition { get; set; }
public string course_type { get; set; }
public string sub_start_date { get; set; }
public string sub_end_date { get; set; }
public string date_begin { get; set; }
public string date_end { get; set; }
public string course_link { get; set; }
}
Deserialization:
var parsed = JObject.Parse(input);
var result = new
ListCoursesResponse
{
success = parsed["success"].Value<bool?>(),
courses =
parsed.Properties()
.Where(prop => prop.Name != "success")
.ToDictionary(prop => prop.Name,
prop => prop.Value.ToObject<Course>())
};

I'm sure it's the worst way to manage this request, but here is my disgusting solution :
public ListCoursesResponse ListCourses(int? categoryId = null)
{
Dictionary<String, Object> dico = null;
if (categoryId != null)
{
List<KeyValuePair<String, Object>> list = new List<KeyValuePair<string, object>>();
list.Add(new KeyValuePair<String, Object>("category", categoryId));
dico = Execute<Dictionary<String, Object>>(String.Format("{0}/{1}", _course, "listCourses"), list.ToArray());
}
dico = Execute<Dictionary<String, Object>>(String.Format("{0}/{1}", _course, "listCourses"));
return dicoToResponse(dico);
}
And :
private ListCoursesResponse dicoToResponse(Dictionary<String, Object> dico)
{
ListCoursesResponse coursesResponse = new ListCoursesResponse();
coursesResponse.success = (Boolean)dico.First(x => x.Key == "success").Value;
if (coursesResponse.success == true)
{
dico.Remove("success");
foreach (Dictionary<String, Object> v in dico.Values)
{
Course course = new Course();
Dictionary<String, Object> values = (Dictionary<String, Object>)v["course_info"];
foreach (String key in values.Keys)
{
switch (key)
{
case "course_id" :
course.Id = (long)values[key];
break;
case "code":
course.Code = (string)values[key];
break;
case "course_name" :
course.Name = (string)values[key];
break;
case "course_description" :
course.Description = (string)values[key];
break;
case "status" :
course.Status = (string)values[key];
break;
case "selling" :
course.IsSalable = (string)values[key] == "0" ? false : true;
break;
case "price" :
course.Price = (string)values[key];
break;
case "subscribe_method" :
course.SubscriptionMethod = (string)values[key];
break;
case "course_edition" :
course.IsEditable = (string)values[key] == "0" ? false : true;
break;
case "course_type" :
course.Type = (string)values[key];
break;
case "sub_start_date" :
course.SubscriptionStartDate = (string)values[key];
break;
case "sub_end_date" :
course.SubscriptionEndDate = (string)values[key];
break;
case "date_begin" :
course.BeginDate = (string)values[key];
break;
case "date_end" :
course.EndDate = (string)values[key];
break;
case "course_link" :
course.Url = (string)values[key];
break;
}
}
coursesResponse.courses.Add(course);
}
}
return coursesResponse;
}

Related

Restsharp error on deserialzation when nested value is null

I'm running into an error when a nested value is null. If the value is not null everything works as expected. This does not happen if the value is not nested.
The error is:
InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
The error happens when I'm checking response.ErrorException != null on the List Contract
Json returned: Contract administrator is nested and blank error: ends is not nested blank and no error:
"result": [
{
"sys_id": "06dc3133db1747808c47499e0b96192e",
"number": "CNTR001234",
"short_description": "Contract 123",
"u_internal_contact": {
"link": "https://website",
"value": "5b4080490a0a3c9e016cb2a9f4eb57b1"
},
"vendor": {
"link": "https://website",
"value": "b7e7c073c0a801690143e7b7d29eb408"
},
"ends": "",
"payment_amount": "60000",
"u_status": "Active",
"starts": "2018-01-01",
"contract_administrator": ""
}
]
}
Code
public class Results
{
public List<Contract> items { get; set; }
}
public class Contract
{
public string sys_id { get; set; }
public string number { get; set; }
public string short_description { get; set; }
public string ends { get; set; }
public string payment_amount { get; set; }
public string u_status { get; set; }
public string starts { get; set; }
public Vendor vendor { get; set; }
public ContractAdmin contract_administrator { get; set; }
public InternalContact u_internal_contact { get; set; }
}
public class Vendor
{
public string link { get; set; }
public string value { get; set; }
}
public class ContractAdmin
{
public string link { get; set; }
public string value { get; set; }
}
public class InternalContact
{
public string link { get; set; }
public string value { get; set; }
}
public class refResults
{
public List<refName> itemName { get; set; }
}
public class refName
{
public string name { get; set; }
}
class ImportContracts
{
public static void ProcessImport()
{
RestClient contractsRequest = new RestClient(Properties.Settings.Default.RestURL);
contractsRequest.Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.userName, Properties.Settings.Default.password);
contractsRequest.AddHandler("application/json", new RestSharp.Deserializers.JsonDeserializer());
RestRequest request = new RestRequest();
request.RootElement = "result";
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<List<Contract>> response = contractsRequest.Execute<List<Contract>>(request);
Console.WriteLine(response.Content);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var ex = new ApplicationException(message, response.ErrorException);
throw ex;
}
foreach (Contract contract in response.Data)
{
//Console.WriteLine(contract.sys_id);
string strVendor = GetName(contract.vendor.link.ToString());
string strInternalContact = GetName(contract.u_internal_contact.link.ToString());
string strContractAdmin = GetName(contract.contract_administrator.ToString());
}
}
static public string GetName (string link)
{
RestClient nameRequest = new RestClient(link);
nameRequest.Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.userName, Properties.Settings.Default.password);
nameRequest.AddHandler("application/json", new RestSharp.Deserializers.JsonDeserializer());
RestRequest requestedName = new RestRequest();
requestedName.RootElement = "result";
requestedName.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<List<refName>> response = nameRequest.Execute<List<refName>>(requestedName);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var ex = new ApplicationException(message, response.ErrorException);
throw ex;
}
foreach (refName refname in response.Data)
{
return refname.name;
}
return "name not found";
}
}
Any help would be appreciated!
Looking at your JSON, "contract_administrator" is not null, it's an empty string. Your contract requires a ContractAdmin object, so what it's likely doing is attempting to cast an empty string to a ContractAdmin.
If you change "contract_administrator" to be null instead of an empty string, I'm willing to bet that it will parse correctly.

Dserialise JSON to object. Some properties always the same, some different

I am trying to build a function where a user can upload a json file.
Each row in the json file can have a different nr of properties(i.e. columns).
5 of these properties are always the same so I want those to be deserialized to an object. The rest of the properties have to go into a dictionary or something.
Here is a json example:
[{
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Bosboom001",
"versie": "812"
},
"Apparaat naam": "",
"Status": "Goedgekeurd",
"Testname1": "",
"Testname3": "2000-01-04T10:37:00+01:00",
"Testname7": "2001-01-03T00:00:00+01:00"
}, {
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Vlaams003",
"versie": "713"
},
"Apparaat naam": "",
"Status": "Goedgekeurd",
"Testname1": "Slecht",
"Testname7": "2000-01-04T10:37:00+01:00",
"Testname9": "2001-01-03T00:00:00+01:00",
"Testname16": "18MOhm",
"Testname23": "OK"
}, {
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Vlaams017",
"versie": "73"
},
"Apparaat naam": "GDR34Z5",
"Status": "Afgekeurd",
"Testname7": "2000-01-04T10:37:00+01:00",
"Testname10": "0,012mA",
"Testname16": "200MOhm",
"Testname23": "200MOhm",
"Testname25": "Afgekeurd",
"Testname31": "0,01mA"
}
]
Here is the class to deserialze to:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
public Dictionary<string, object> testNames { get; set; }
}
public class Apparaat
{
public string project { get; set; }
public string versie { get; set; }
}
And here is the controller
public IActionResult Upload(IFormFile file)
{
string fileContent = null;
using (var reader = new StreamReader(file.OpenReadStream()))
{
fileContent = reader.ReadToEnd();
}
List<KeuringRegel> keuringRegelList = JsonConvert.DeserializeObject<List<KeuringRegel>>(fileContent);
//More stuff here
}
The json successfully deserializes but the testNames value is always null. I understand why, because there is no testNames property in the Json file. However, how do I achieve what I want? I am no Json expert.
One way you can do this, assuming that there is only testNameNNNN entries as supplemental values, is to use the JsonExtensionDataAttribute like this:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
[JsonExtensionData()]
public Dictionary<string, object> testNames { get; set; }
}
This will give you the values whos don't fall into one of the other properties:
It's a bit of a "blunt instrument" but you could always perform some post-processing on the returned instances of KeuringRegel to remove any errant entries from testNames (i.e. things that don't match the pattern testNameNNNN).
If your JSON does contain things that don't match the pattern testNameNNNN which would therefore get included, you could implement a custom class for the testNames property:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
[JsonExtensionData()]
public TestNames testNames { get; set; }
}
public class TestNames : Dictionary<string, object>
{
public new void Add(string key, object value)
{
if (key.StartsWith("testname", StringComparison.OrdinalIgnoreCase))
{
base.Add(key, value);
}
}
}
This will check each item that is added to the testNames dictionary and prevent its addition if (as in my comment where I had an item in the JSON of "badgerBadgetCatCat": 3) it doesn't match the pattern.
Here u are full example
internal class Program
{
private static void Main(string[] args)
{
var str = #"[{
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Bosboom001"",
""versie"": ""812""
},
""Apparaat naam"": """",
""Status"": ""Goedgekeurd"",
""Testname1"": """",
""Testname3"": ""2000-01-04T10:37:00+01:00"",
""Testname7"": ""2001-01-03T00:00:00+01:00""
}, {
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Vlaams003"",
""versie"": ""713""
},
""Apparaat naam"": """",
""Status"": ""Goedgekeurd"",
""Testname1"": ""Slecht"",
""Testname7"": ""2000-01-04T10:37:00+01:00"",
""Testname9"": ""2001-01-03T00:00:00+01:00"",
""Testname16"": ""18MOhm"",
""Testname23"": ""OK""
}, {
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Vlaams017"",
""versie"": ""73""
},
""Apparaat naam"": ""GDR34Z5"",
""Status"": ""Afgekeurd"",
""Testname7"": ""2000-01-04T10:37:00+01:00"",
""Testname10"": ""0,012mA"",
""Testname16"": ""200MOhm"",
""Testname23"": ""200MOhm"",
""Testname25"": ""Afgekeurd"",
""Testname31"": ""0,01mA""
}
]";
var sw = Stopwatch.StartNew();
var result = Mapper.Map(str);
sw.Stop();
Console.WriteLine($"Deserialized at {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} tiks)");
}
public static class Mapper
{
static Mapper()
{
List<string> names = new List<string>();
IEnumerable<PropertyInfo> p = typeof(KeuringRegel).GetProperties().Where(c => c.CanRead && c.CanWrite);
foreach (var propertyInfo in p)
{
var attr = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>();
names.Add(attr != null ? attr.PropertyName : propertyInfo.Name);
}
Properties = names.ToArray();
}
private static string[] Properties { get; }
public static KeuringRegel[] Map(string str)
{
var keuringRegels = JsonConvert.DeserializeObject<KeuringRegel[]>(str);
var objs = JsonConvert.DeserializeObject(str) as IEnumerable;
var objectList = new List<JObject>();
foreach (JObject obj in objs)
objectList.Add(obj);
for (var i = 0; i < keuringRegels.Length; i++)
{
keuringRegels[i].testNames = new Dictionary<string, object>();
foreach (var p in objectList[i].Children().OfType<JProperty>().Where(c => !Properties.Contains(c.Name)).ToArray())
keuringRegels[i].testNames.Add(p.Name, p.Value);
}
return keuringRegels;
}
}
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
public Dictionary<string, object> testNames { get; set; }
}
public class Apparaat
{
public string project { get; set; }
public string versie { get; set; }
}
}

SingleValueArrayConverter of an array returning null properties

I'm trying to use a custom singlearrayconverter to access the values of my json array, but I keep getting null values, I'm wondering where I could be doing something wrong.
I have the following JSON:
{
"message": "success",
"action": "user_info",
"data": {
"profile_info": {
"querying": "0",
"tps": {
"1": {
"profile_url": "anotherfakeurl",
"file_hash": "hash",
"icon_path": "",
"time_of_insertion": "0000-00-00 00:00:00",
"tp_id": "1",
"user_id": "4",
"tp_user_id": "1377839182243200",
"last_use": "0000-00-00 00:00:00",
"active": "0",
"user_display": "it's a me",
"selected": "1",
"prof_pic": "fakeurl"
}
}
}
}
}
And I have the following datamodel:
[JsonProperty("tps")]
[JsonConverter(typeof(SingleValueArrayConverter<Tps>))]
public List<Tps> TpsList { get; set; }
And I'm using this converter:
public class SingleValueArrayConverter<T> : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object retVal = new Object();
if (reader.TokenType == JsonToken.StartObject)
{
T instance = (T)serializer.Deserialize(reader, typeof(T));
retVal = new List<T>() { instance };
}
else if (reader.TokenType == JsonToken.StartArray)
{
retVal = serializer.Deserialize(reader, objectType);
}
return retVal;
}
public override bool CanConvert(Type objectType)
{
return false;
}
}
And every other value is correct, it even gives me the right array count. But the contents of each Tps property are either empty or null.
Thank you,
edit: Here is the full Data Model.
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class UserInfo
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("action")]
public string Action { get; set; }
[JsonProperty("data")]
public Data Data { get; set; }
}
public class Data
{
[JsonProperty("profile_info")]
public ProfileInformation ProfileInformation { get; set; }
}
public class ProfileInformation
{
[JsonProperty("querying")]
public string Querying { get; set; }
[JsonProperty("tps")]
[JsonConverter(typeof(SingleValueArrayConverter<Tps>))]
public List<Tps> TpsList { get; set; }
}
public class Tps
{
[JsonProperty("profile_url")]
public string ProfileUrl { get; set; }
[JsonProperty("file_hash")]
public string FileHash { get; set; }
[JsonProperty("icon_path")]
public string IconPath { get; set; }
[JsonIgnore]
[JsonProperty("time_of_insertion")]
public DateTime TimeOfInsertion { get; set; }
[JsonProperty("tp_id")]
public int TpId { get; set; }
[JsonProperty("user_id")]
public int UserId { get; set; }
[JsonProperty("tp_user_id")]
public long TpUserId { get; set; }
[JsonIgnore]
[JsonProperty("last_use")]
public DateTime LastUse { get; set; }
[JsonProperty("active")]
public string Active { get; set; }
[JsonProperty("user_display")]
public string UserDisplay { get; set; }
[JsonProperty("selected")]
public string Selected { get; set; }
[JsonProperty("prof_pic")]
public string ProfilePicture { get; set; }
}
I am not saying this is the most elegant or best way around, but it works. You can use a dictionary to achieve the desired bahavior. So, lose the converter, then move back and forth between a list and a dictionary, key being that TpId field it seems.
public class ProfileInformation
{
[JsonProperty("querying")]
public string Querying { get; set; }
List<Tps> _tpsList = null;
[JsonIgnore]
public List<Tps> TpsList {
get {
if (_tpsList == null && _tpsDict != null) {
_tpsList = _tpsDict.Values.ToList();
}
return _tpsList;
}
set { _tpsList = value; }
}
Dictionary<int, Tps> _tpsDict = null;
[JsonProperty("tps")]
public Dictionary<int, Tps> TpsDict {
get {
if (_tpsDict == null && _tpsList != null) {
_tpsDict = _tpsList.ToDictionary(x => x.TpId);
}
return _tpsDict;
}
set { _tpsDict = value; }
}
}
Test
var userInfo = new UserInfo() {
Action = "user_info",
Message = "success",
Data = new Data() {
ProfileInformation = new ProfileInformation() {
Querying = "0",
TpsList = new List<Tps>() {
new Tps() {
Active="0",
FileHash = "hash",
IconPath="",
LastUse= DateTime.MinValue,
ProfileUrl = "anotherfakeurl",
ProfilePicture = "fakeurl",
Selected = "1",
TimeOfInsertion = DateTime.MinValue,
TpId = 1,
TpUserId = 1377839182243200L,
UserDisplay = "it's a me",
UserId = 4
} } } } };
string json = JsonConvert.SerializeObject(userInfo, Formatting.Indented);
var newUserInfo = JsonConvert.DeserializeObject<UserInfo> (json);
Assert.AreEqual(newUserInfo.Data.ProfileInformation.TpsList.Count,1);
Assert.AreEqual(newUserInfo.Data.ProfileInformation.TpsDict.Count,1);

Json deserialize not working in C# window 2012 servers

I am trying to deserialize the json string from Rest webserive in C#. Following is jsonstring and classes I used. But after deserialize it is giving null/empty value on server.But in local its working as expected. So what's going wrong with me?
Json String
{
"error": false,
"parameters": [
{
"Programs": "ZZ_UNUSED_EU-01pp-Q669;EU-PPP-O003;ZZ_UNUSED_EU-PPP-CO05;100000;pbse;EU-m110-2007;EU-zz33-L053;EU-zz21-z084;ZZ_UNUSED_EU-01pp-Q875;EU-zz05-L029;ZZ_UNUSED_EU-RAD-003;ZZ_UNUSED_EU-RAD-004;ZZ_UNUSED_EU-RAD-007;ZZ_UNUSED_EU-RAD-012;ZZ_UNUSED_EU-RAD-015;ZZ_UNUSED_EU-zz22-RF21;ZZ_UNUSED_EU-PPP-CO130;ZZ_UNUSED_EU-01pp-Q962;ZZ_UNUSED_EU-01pp-Q963;EU-LandR-COM;EU-01pp-O960;EU-SI-HP-INTL;G_PC_SQ;G_Survey_Inv_TPE-FY11;G_MADO_3Com;G_eLocator_AIS;G_eLocator_ATP;G_eLocator_SCE;G_eLocator_TECI;G_L&R_SCREENED;G_L&R_CASE_OPEN;EU-MDF-Tool;EU-DI-SPT-FLASHPRO;EU-DI-SPT-FLASHPRO-FY11;EU-DI-SPT-FLASHPRO-FY12;G_SPT_PCLM_Prospect;G_SPT_PCLM_Enrolled;SPEC_P1_S1_GOLD_PPS_CAN;G_SPT_Joint_Business_Planning;EU_RET_CE_SCOPE;G_PARTNER_HPQ;ZZ_UNUSED_EU-01pp-O972;SPEC_P1_SERV_SILV_CAN;SPEC_P1_STOR_SILV_CAN;SPEC_P1_NW_SILV_CAN;SPEC_P1_S1_SILV_CAN;PM_P1_PLAT_PART_CAN;PM_P1_SILV_PART_PPS_SM_CAN;SPEC_P1_WK_GOLD_CAN;ZZ_UNUSED_EU-01pp-Q018;"
},
{
"PartnerSubTypes": "G_Tgt_Commercial_T2_Reseller_S;SSP;Supplies Commercial;"
},
{
"CompanyNumber": "29682"
},
{
"PartnerNameHQ": "151070026"
},
{
"SiteIdentifier": "UPP"
},
{
"LastName": "Isaksson"
},
{
"HPInternalUser": "F"
},
{
"PhysAdLine1": "?STRA HAMNEN 1"
},
{
"HPPUserId": "989d35449261b4348e2f477260b1eacc"
},
{
"PartnerName": "Misco AB"
},
{
"PhysAdLine2": ""
},
{
"PhysAdLine3": ""
},
{
"PrimaryChannelSegment": "TDL"
},
{
"HPOrg": "HP Sweden"
},
{
"LastLoginDate": "1426841482160"
},
{
"PartnerPhone": ""
},
{
"PartnerLegalName": "Misco AB"
},
{
"HPOrgs": "Default Organization;HP Sweden;"
},
{
"FirstName": "Joakim"
},
{
"CountryCode": "SE"
},
{
"PreferredLanguageCode": "en"
},
{
"IsPartnerAdmin": "T"
},
{
"PartnerProIdHQ": "1-2GF-564"
},
{
"Accreditations": "G_PM_P1_PLAT_PAR_PP_BU;G_SEGT_EG_SERV_GROWTH;G_SEGT_EG_TS_GROWTH;G_FC_AGR_T2;G_S1_Prospect;G_GPL_P1_PPS_SM;ZZ_UNUSED_EU-zz46-c103;EU-02pp-O138;G_P1_Specialist_Enrolled;G_P1_Specialist_Candidate;G_S1_EXP;G_GPL_P1_EG_BUS;G_GPL_P1_PPS;G_PM_P1_PLAT_PAR;G_PM_P1_BUS_SP_EG_BU;G_GPL_P1_WK;G_P1_Preferred_Candidate;G_P1_Specialist_Enrolled;G_S1_Candidate;G_SEGT_PAN-EG_GROWTH;G_SEGT_EG_NW_GROWTH;G_SEGT_EG_STOR_GROWTH;FY15_P1_STOR_SILV_TGT;FY15_P1_S1_SILV_TGT;FY15_P1_NW_SILV_TGT;G_GPL_P1_S1_P;G_S1_Prospect;FY15_P1_SERV_SILV_TGT;G_PM_P1_BUS_SP_EG;G_PM_P1_PLAT_PAR_PP;G_PM_P1_SILV_PAR_PP_SM;G_SPEC_P1_S1_GOLD_P;G_SPEC_P1_WK_GOLD;ZZ_UNUSED_EU-I&P;ZZ_UNUSED_EU-01pp-Q586;"
},
{
"PhysCountry": "Sweden"
},
{
"PhysCity": "LIDK?PING"
},
{
"PartnerProId": "1-2GF-564"
},
{
"Tier": ""
},
{
"Email": "itg.itg.joakim.isaksson#misco.se"
},
{
"PhysPostalCode": "531 40"
},
{
"PartnerFax": ""
}
]
}
Rest webservice call
//string requestUrl = "http://localhost:8080/RestWSPartner/parameter";
string requestUrl = "https://upp-itg-moonshot-gslb.austin.hp.com/delegate/esmtokenvalidation/v1?token="+tokenId;
Log.WriteInfo("requestUrl in RestWS==>" + requestUrl);
do
{
HttpWebRequest request = HttpWebRequest.Create(requestUrl) as HttpWebRequest;
request.Method = "GET";
request.ContentType = "application/json; charset=UTF-8";//charset=UTF-8";
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(PartnerData));
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream receiveStream = response.GetResponseStream();
restResponse = jsonSerializer.ReadObject(receiveStream) as PartnerData;
Log.WriteInfo("restResponse.error ==>" + restResponse.error);
Log.WriteInfo("restResponse.message ==>" + restResponse.message);
if (restResponse.error.Equals("false"))
{
// Log.WriteInfo("restResponse===UserId>" + restResponse.parameters.HPPUserId);
Log.WriteInfo("restResponse===PartnerProId>" + restResponse.parameters.PreferredLanguageCode);
Log.WriteInfo("restResponse===PartnerProId>" + restResponse.parameters.FirstName);
Log.WriteInfo("success.. Break");
break;
}
my class
namespace ProductguideNordic
{
[DataContract]
public class PartnerData
{
[DataMember(Name = "error")]
public string error { get; set; }
[DataMember(Name = "message")]
public string message { get; set; }
[DataMember(Name = "parameters")]
public Paramter parameters { get; set; }
}
[DataContract]
public class Paramter
{
[DataMember(Name = "Programs")]
public string Programs { set; get; }
[DataMember(Name = "PartnerSubTypes")]
public string PartnerSubTypes { set; get; }
[DataMember(Name = "CompanyNumber")]
public string CompanyNumber { set; get; }
[DataMember(Name = "PartnerNameHQ")]
public string PartnerNameHQ { set; get; }
[DataMember(Name = "SiteIdentifier")]
public string SiteIdentifier { set; get; }
[DataMember(Name = "LastName")]
public string LastName { set; get; }
[DataMember(Name = "HPInternalUser")]
public string HPInternalUser { set; get; }
[DataMember(Name = "PhysAdLine1")]
public string PhysAdLine1 { set; get; }
[DataMember(Name = "HPPUserId")]
public string HPPUserId { set; get; }
[DataMember(Name = "PartnerName")]
public string PartnerName { set; get; }
[DataMember(Name = "PhysAdLine2")]
public string PhysAdLine2 { set; get; }
[DataMember(Name = "PhysAdLine3")]
public string PhysAdLine3 { set; get; }
[DataMember(Name = "PrimaryChannelSegment")]
public string PrimaryChannelSegment { set; get; }
[DataMember(Name = "HPOrg")]
public string HPOrg { set; get; }
[DataMember(Name = "LastLoginDate")]
public string LastLoginDate { set; get; }
[DataMember(Name = "PartnerPhone")]
public string PartnerPhone { set; get; }
[DataMember(Name = "PartnerLegalName")]
public string PartnerLegalName { set; get; }
[DataMember(Name = "HPOrgs")]
public string HPOrgs { set; get; }
[DataMember(Name = "FirstName")]
public string FirstName { set; get; }
[DataMember(Name = "CountryCode")]
public string CountryCode { set; get; }
[DataMember(Name = "PreferredLanguageCode")]
public string PreferredLanguageCode { set; get; }
[DataMember(Name = "IsPartnerAdmin")]
public string IsPartnerAdmin { set; get; }
[DataMember(Name = "PartnerProIdHQ")]
public string PartnerProIdHQ { set; get; }
[DataMember(Name = "Accreditations")]
public string Accreditations { set; get; }
[DataMember(Name = "PhysCountry")]
public string PhysCountry { set; get; }
[DataMember(Name = "physCity")]
public string physCity { set; get; }
[DataMember(Name = "PartnerProId")]
public string PartnerProId { set; get; }
[DataMember(Name = "Tier")]
public string Tier { set; get; }
[DataMember(Name = "Email")]
public string Email { set; get; }
[DataMember(Name = "PhysPostalCode")]
public string PhysPostalCode { set; get; }
[DataMember(Name = "PartnerFax")]
public string PartnerFax { set; get; }
[DataMember(Name = "PortalSessionId")]
public string PortalSessionId { set; get; }
}
}
In my local with local URL, im able to deserialize the json string and assigned to partnerdata. In server (windows 2012) after deployed into IIS(8.5) parameters values are null/ empty and there was no error while deserialize . Rest WS sending expected response's. and restResponse.error this value deserialized correctly but parameters are not deserialized.
So what's going wrong with me?
In the JSON string you show, "parameters" is an array of name/value pairs:
{
"error": false,
"parameters": [
{
"Programs": "ZZ_UNUSED_EU-01pp-Q669;EU-PPP-O003;ZZ_UNUSED_EU-PPP-CO05;100000;pbse;EU-m110-2007;EU-zz33-L053;EU-zz21-z084;ZZ_UNUSED_EU-01pp-Q875;EU-zz05-L029;ZZ_UNUSED_EU-RAD-003;ZZ_UNUSED_EU-RAD-004;ZZ_UNUSED_EU-RAD-007;ZZ_UNUSED_EU-RAD-012;ZZ_UNUSED_EU-RAD-015;ZZ_UNUSED_EU-zz22-RF21;ZZ_UNUSED_EU-PPP-CO130;ZZ_UNUSED_EU-01pp-Q962;ZZ_UNUSED_EU-01pp-Q963;EU-LandR-COM;EU-01pp-O960;EU-SI-HP-INTL;G_PC_SQ;G_Survey_Inv_TPE-FY11;G_MADO_3Com;G_eLocator_AIS;G_eLocator_ATP;G_eLocator_SCE;G_eLocator_TECI;G_L&R_SCREENED;G_L&R_CASE_OPEN;EU-MDF-Tool;EU-DI-SPT-FLASHPRO;EU-DI-SPT-FLASHPRO-FY11;EU-DI-SPT-FLASHPRO-FY12;G_SPT_PCLM_Prospect;G_SPT_PCLM_Enrolled;SPEC_P1_S1_GOLD_PPS_CAN;G_SPT_Joint_Business_Planning;EU_RET_CE_SCOPE;G_PARTNER_HPQ;ZZ_UNUSED_EU-01pp-O972;SPEC_P1_SERV_SILV_CAN;SPEC_P1_STOR_SILV_CAN;SPEC_P1_NW_SILV_CAN;SPEC_P1_S1_SILV_CAN;PM_P1_PLAT_PART_CAN;PM_P1_SILV_PART_PPS_SM_CAN;SPEC_P1_WK_GOLD_CAN;ZZ_UNUSED_EU-01pp-Q018;"
},
{
"PartnerSubTypes": "G_Tgt_Commercial_T2_Reseller_S;SSP;Supplies Commercial;"
},
Your code is attempting to deserialize parameters as a single object with many properties, e.g.:
{
"error": false,
"parameters": {
"Programs": "ZZ_UNUSED_EU-01pp-Q669;EU-PPP-O003;ZZ_UNUSED_EU-PPP-CO05;100000;pbse;EU-m110-2007;EU-zz33-L053;EU-zz21-z084;ZZ_UNUSED_EU-01pp-Q875;EU-zz05-L029;ZZ_UNUSED_EU-RAD-003;ZZ_UNUSED_EU-RAD-004;ZZ_UNUSED_EU-RAD-007;ZZ_UNUSED_EU-RAD-012;ZZ_UNUSED_EU-RAD-015;ZZ_UNUSED_EU-zz22-RF21;ZZ_UNUSED_EU-PPP-CO130;ZZ_UNUSED_EU-01pp-Q962;ZZ_UNUSED_EU-01pp-Q963;EU-LandR-COM;EU-01pp-O960;EU-SI-HP-INTL;G_PC_SQ;G_Survey_Inv_TPE-FY11;G_MADO_3Com;G_eLocator_AIS;G_eLocator_ATP;G_eLocator_SCE;G_eLocator_TECI;G_L&R_SCREENED;G_L&R_CASE_OPEN;EU-MDF-Tool;EU-DI-SPT-FLASHPRO;EU-DI-SPT-FLASHPRO-FY11;EU-DI-SPT-FLASHPRO-FY12;G_SPT_PCLM_Prospect;G_SPT_PCLM_Enrolled;SPEC_P1_S1_GOLD_PPS_CAN;G_SPT_Joint_Business_Planning;EU_RET_CE_SCOPE;G_PARTNER_HPQ;ZZ_UNUSED_EU-01pp-O972;SPEC_P1_SERV_SILV_CAN;SPEC_P1_STOR_SILV_CAN;SPEC_P1_NW_SILV_CAN;SPEC_P1_S1_SILV_CAN;PM_P1_PLAT_PART_CAN;PM_P1_SILV_PART_PPS_SM_CAN;SPEC_P1_WK_GOLD_CAN;ZZ_UNUSED_EU-01pp-Q018;"
"PartnerSubTypes": ""G_Tgt_Commercial_T2_Reseller_S;SSP;Supplies Commercial;""
In other words, the JSON you are receiving for "parameters"corresponds to a List<Dictionary<string, string>> with UseSimpleDictionaryFormat = false, rather than a single POCO with various properties.
Update
Given that this is a legacy application using an older version of .Net (possibly with some configuration issues, as the var keyword is causing you to have a compiler error), I am going to suggest switching to JavaScriptSerializer which is also a built-in .Net component. Change your data model as follows:
public class PartnerDataDictionary
{
public PartnerDataDictionary()
{
this.ParameterDictionary = new Dictionary<string, string>();
}
string _error;
public string error { get { return _error; } set { _error = value; } }
string _message;
public string message { get { return _message; } set { _message = value; } }
[System.Web.Script.Serialization.ScriptIgnore]
public Dictionary<string, string> ParameterDictionary { get; set; }
public List<Dictionary<string, string>> parameters
{
get
{
List<Dictionary<string, string>> dictList = new List<Dictionary<string, string>>();
foreach (KeyValuePair<string, string> pair in ParameterDictionary)
{
Dictionary<string, string> subDict = new Dictionary<string,string>(1);
subDict[pair.Key] = pair.Value;
dictList.Add(subDict);
}
return dictList;
}
set
{
if (value == null)
{
ParameterDictionary = new Dictionary<string, string>();
return;
}
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (Dictionary<string, string> entry in value)
foreach (KeyValuePair<string, string> pair in entry)
dict.Add(pair.Key, pair.Value);
ParameterDictionary = dict;
}
}
public string GetParameter(string key)
{
string value;
if (ParameterDictionary.TryGetValue(key, out value))
return value;
return null;
}
public void SetParameter(string key, string value)
{
ParameterDictionary[key] = value;
}
// Add other properties as needed, marking them as `ScriptIgnore`:
[System.Web.Script.Serialization.ScriptIgnore]
public string Programs
{
get { return GetParameter("Programs"); }
set { SetParameter("Programs", value); }
}
}
What I am doing here is reading the JSON as a list of dictionaries, then combining them into a dictionary in the setter for ease of use.
Then you can read and write your JSON parameters as follows:
PartnerDataDictionary data = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<PartnerDataDictionary>(json);
string programs = data.Programs;
Debug.WriteLine(programs);
Original Answer
You could simply change your PartnerData class to have such a list of dictionaries. If you want to continue to use your current data model, and also use DataContractJsonSerializer, you are going to need to introduce a data contract surrogate to do the conversion:
public class ObjectToPropertyDictionaryArraySurrogate<T> : IDataContractSurrogate
{
class ListDictionaryArray : List<Dictionary<string, string>>
{
}
#region IDataContractSurrogate Members
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
throw new NotImplementedException();
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
throw new NotImplementedException();
}
public Type GetDataContractType(Type type)
{
if (type == typeof(T))
return typeof(ListDictionaryArray);
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj is ListDictionaryArray)
{
var array = (ListDictionaryArray)obj;
var dict = array.SelectMany(pair => pair).ToDictionary(pair => pair.Key, pair => pair.Value);
var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(dict);
return DataContractJsonSerializerHelper.GetObject<T>(json, new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });
}
return obj;
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj.GetType() == typeof(T))
{
var json = DataContractJsonSerializerHelper.GetJson((T)obj, new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });
var dict = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, string>>(json);
var array = new ListDictionaryArray();
array.AddRange(dict.Select(pair => new[] { pair }.ToDictionary(p => p.Key, p => p.Value)));
return array;
}
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
throw new NotImplementedException();
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
#endregion
}
public static class DataContractJsonSerializerHelper
{
public static string GetJson<T>(T obj, DataContractJsonSerializer serializer)
{
using (var memory = new MemoryStream())
{
serializer.WriteObject(memory, obj);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
return reader.ReadToEnd();
}
}
}
public static string GetJson<T>(T obj)
{
var serializer = new DataContractJsonSerializer(typeof(T));
return GetJson(obj, serializer);
}
public static string GetJson<T>(T obj, DataContractJsonSerializerSettings settings)
{
var serializer = new DataContractJsonSerializer(obj.GetType(), settings);
return GetJson<T>(obj, serializer);
}
public static T GetObject<T>(string json, DataContractJsonSerializer serializer)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = serializer.ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json)
{
var serializer = new DataContractJsonSerializer(typeof(T));
return GetObject<T>(json, serializer);
}
public static T GetObject<T>(string json, DataContractJsonSerializerSettings settings)
{
var serializer = new DataContractJsonSerializer(typeof(T), settings);
return GetObject<T>(json, serializer);
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
And then use it like:
var settings = new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true,
DataContractSurrogate = new ObjectToPropertyDictionaryArraySurrogate<Paramter>(),
};
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(PartnerData), settings);

Parsing a complex JSON result with C#

I am trying to parse the following complex JSON result, which is returned from the Zoho Crm API:
{
"response":
{
"result":
{
"Contacts":
{
"row":
[
{
"no":"1",
"FL":
[
{
"content":"555555000000123456",
"val":"CONTACTID"
},
{
"content":"555555000000012345",
"val":"SMOWNERID"
},
{
"content":"John Doe",
"val":"Contact Owner"
},
{
"content":"Pete",
"val":"First Name"
},
{
"content":"Smith",
"val":"Last Name"
},
{
"content":"pete#mail.com",
"val":"Email"
},
{
"content":"5555551000000012346",
"val":"SMCREATORID"
},
{
"content":"Jane Doe",
"val":"Created By"
},
{
"content":"555555000000012347",
"val":"MODIFIEDBY"
},
{
"content":"Doris Doe",
"val":"Modified By"
},
{
"content":"2013-06-14 17:24:10",
"val":"Created Time"
},
{
"content":"2013-06-14 17:24:10",
"val":"Modified Time"
},
{
"content":"2013-06-14 17:28:05",
"val":"Last Activity Time"
}
]
},
{
...
}
]
}
},
"uri":"/crm/private/json/Contacts/getRecords"
}
}
Here is how my Object looks:
public class Contact
{
[JsonProperty(PropertyName = "CONTACTID")]
public string ContactID { get; set; }
[JsonProperty(PropertyName = "SMOWNERID")]
public string OwnerID { get; set; }
[JsonProperty(PropertyName = "Contact Owner")]
public string ContactOwner { get; set; }
[JsonProperty(PropertyName = "First Name")]
public string FirstName { get; set; }
[JsonProperty(PropertyName = "Last Name")]
public string LasName { get; set; }
[JsonProperty(PropertyName = "Email")]
public string Email { get; set; }
[JsonProperty(PropertyName = "SMCREATORID")]
public string CreatorID { get; set; }
[JsonProperty(PropertyName = "Created By")]
public string CreatedBy { get; set; }
[JsonProperty(PropertyName = "MODIFIEDBY")]
public string ModifiedByID { get; set; }
[JsonProperty(PropertyName = "Modified By")]
public string ModifiedBy { get; set; }
[JsonProperty(PropertyName = "Created Time")]
public DateTime CreatedTime { get; set; }
[JsonProperty(PropertyName = "Modified Time")]
public DateTime ModifiedTime { get; set; }
[JsonProperty(PropertyName = "Last Activity Time")]
public DateTime LastActivityTime { get; set; }
}
The "row" pattern repeats (no 1, 2, 3 ...) so what I am basically trying to get is a Generic List of Objects of this type. I am trying to using JSON.NET, but I am open to other suggestions if it makes this any easier.
This doesn't work in this case obviously:
var response = JsonConvert.DeserializeObject<Contact>(jsonString);
And neither does this:
var deserializedObjects = JsonConvert.DeserializeObject<List<Contact>>(jsonString);
Here is a workaround I have put together to parse this using JavaScriptSerializer, but it is by far one of my worst code blocks ever!
List<Contact> loContactList = new List<Contact>();
Contact loContact = null;
Dictionary<string, object> dictionary = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(jsonString);
var response = (Dictionary<string, object>)dictionary["response"];
var result = (Dictionary<string, object>)response["result"];
var contacts = (Dictionary<string, object>)result["Contacts"];
var row = (ArrayList)contacts["row"];
foreach (var item in row)
{
var loArrayItem = (Dictionary<string, object>)item;
var fl = (ArrayList)loArrayItem["FL"];
loContact = new Contact();
foreach (var contactitem in fl)
{
var contactdict = (Dictionary<string, object>)contactitem;
string val = (string)contactdict["val"];
string content = (string)contactdict["content"];
if (val == "CONTACTID")
{
loContact.ContactID = content;
}
else if (val == "SMOWNERID")
{
loContact.OwnerID = content;
}
else if (val == "Contact Owner")
{
loContact.ContactOwner = content;
}
else if (val == "First Name")
{
loContact.FirstName = content;
}
else if (val == "Last Name")
{
loContact.LastName = content;
}
else if (val == "Email")
{
loContact.Email = content;
}
else if (val == "SMCREATORID")
{
loContact.CreatorID = content;
}
else if (val == "Created By")
{
loContact.CreatedBy = content;
}
else if (val == "MODIFIEDBY")
{
loContact.ModifiedByID = content;
}
else if (val == "Modified By")
{
loContact.ModifiedBy = content;
}
else if (val == "Created Time")
{
loContact.CreatedTime = Convert.ToDateTime(content);
}
else if (val == "Modified Time")
{
loContact.ModifiedTime = Convert.ToDateTime(content);
}
else if (val == "Last Activity Time")
{
loContact.LastActivityTime = Convert.ToDateTime(content);
}
}
loContactList.Add(loContact);
}
I have gone through other similar posts on StackOverflow and none of them seem to provide a solution for this problem. Does anyone have a solution for this? My goal is to parse this JSON response in a more elegant way, which doesn't involve a million dictionary objects and ArrayList! Any help would be appreciated.
Thanks,
Pete
Update 7/2/13:
Based on Manvik's suggestion, I put together the following additional solution:
public class ResponseActual
{
[JsonProperty("response")]
public Response2 Response { get; set; }
}
public class Response2
{
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("uri")]
public string Uri { get; set; }
}
public class Result
{
[JsonProperty("Contacts")]
public Contacts Contacts { get; set; }
}
public class Contacts
{
[JsonProperty("row")]
public IList<Row> Row { get; set; }
}
public class Row
{
[JsonProperty("no")]
public string No { get; set; }
[JsonProperty("FL")]
public IList<FL> FL { get; set; }
}
public class FL
{
[JsonProperty("content")]
public string Content { get; set; }
[JsonProperty("val")]
public string Val { get; set; }
}
List<Contact> loContactList = new List<Contact>();
Contact loContact = null;
ResponseActual respone = JsonConvert.DeserializeObject<ResponseActual>(jsonString);
foreach (var row in respone.Response.Result.Contacts.Row)
{
loContact = new Contact();
var rowItem = row.FL.ToList();
try { loContact.ContactID = rowItem.Where<FL>((s, t) => s.Val == "CONTACTID").Select(x => x.Content).Single(); }
catch { }
try { loContact.OwnerID = rowItem.Where<FL>((s, t) => s.Val == "SMOWNERID").Select(x => x.Content).Single(); }
catch { }
try { loContact.ContactOwner = rowItem.Where<FL>((s, t) => s.Val == "Contact Owner").Select(x => x.Content).Single(); }
catch { }
try { loContact.FirstName = rowItem.Where<FL>((s, t) => s.Val == "First Name").Select(x => x.Content).Single(); }
catch { }
try { loContact.LastName = rowItem.Where<FL>((s, t) => s.Val == "Last Name").Select(x => x.Content).Single(); }
catch { }
try { loContact.Email = rowItem.Where<FL>((s, t) => s.Val == "Email").Select(x => x.Content).Single(); } catch { }
try { loContact.CreatorID = rowItem.Where<FL>((s, t) => s.Val == "SMCREATORID").Select(x => x.Content).Single(); }
catch { }
try { loContact.CreatedBy = rowItem.Where<FL>((s, t) => s.Val == "Created By").Select(x => x.Content).Single(); }
catch { }
try { loContact.ModifiedByID = rowItem.Where<FL>((s, t) => s.Val == "MODIFIEDBY").Select(x => x.Content).Single(); }
catch { }
try { loContact.ModifiedBy = rowItem.Where<FL>((s, t) => s.Val == "Modified By").Select(x => x.Content).Single(); }
catch { }
try { loContact.CreatedTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Created Time").Select(x => x.Content).Single()); }
catch { }
try { loContact.ModifiedTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Modified Time").Select(x => x.Content).Single()); }
catch { }
try { loContact.LastActivityTime = Convert.ToDateTime(rowItem.Where<FL>((s, t) => s.Val == "Last Activity Time").Select(x => x.Content).Single()); }
catch { }
loContactList.Add(loContact);
}
Use the below classes for de-serializing using JSON.Net
public class ResponseActual
{
[JsonProperty("response")]
public Response2 Response { get; set; }
}
public class Response2
{
[JsonProperty("result")]
public Result Result { get; set; }
[JsonProperty("uri")]
public string Uri { get; set; }
}
public class Result
{
[JsonProperty("Contacts")]
public Contacts Contacts { get; set; }
}
public class Contacts
{
[JsonProperty("row")]
public IList<Row> Row { get; set; }
}
public class Row
{
[JsonProperty("no")]
public string No { get; set; }
[JsonProperty("FL")]
public IList<FL> FL { get; set; }
}
public class FL
{
[JsonProperty("content")]
public string Content { get; set; }
[JsonProperty("val")]
public string Val { get; set; }
}
//To De-serialize
ResponseActual respone = JsonConvert.DeserializeObject<ResponseActual>(jSON_sTRING)
//Get the contacts list
List<FL> contacts = respone.Response.Result.Contacts.Row[0].FL.ToList();
//Now Get the required value using LINQ
var value = contacts.Where<FL>((s, e) => s.Val =="Email").Select(x=>x.Content).Single();
You may also checkout this -
Deserializing JSON to .NET object using Newtonsoft (or LINQ to JSON maybe?)
You need to include the following portion of JSON in your deserialization object Type :
{
"response":
{
"result":
{
"Contacts":
{
"row":
[
{
"no":"1",
"FL":
Class type : 'Contact' is inadequate.
you can use this code:
dynamic dictionary = (JsonConvert.DeserializeObject>(jsonstring))["response"];
var result = dictionary.result;
var contact= result.Contacts;
var row= contact.row;
foreach (var item in row)
{
var no= item.no;
}
Can I ask you something? Are you the one exporting the JSON? I ask this because the format is quite weird and it does get in the way of your code.
A simpler format would allow you to serialize the string pretty much in a direct way.

Categories

Resources