How to deserialize JSON without static key/property names - c#

Hello I have problem with deserializing IRestResponse.Content JSON response.
{
"49":
{
"9345": "2018-10-11",
"106": null,
"107": "4222238842",
"108": "CompanyName",
"8210": "2018-11-11/1",
"110": "00-300",
"109": "Street",
"112": "Country",
"18418": null,
"18420": "S\u0141ON",
"18422": "OtherString",
"9338": null,
"111": "City"
}
}
I have tried some webpage's or built in VisualStudio converter but It gives my something like this.
public class Rootobject
{
public _49 _49 { get; set; }
}
public class _49
{
public string _9345 { get; set; }
public object _106 { get; set; }
public string _107 { get; set; }
public string _108 { get; set; }
public string _8210 { get; set; }
public string _110 { get; set; }
public string _109 { get; set; }
public string _112 { get; set; }
public object _18418 { get; set; }
public string _18420 { get; set; }
public string _18422 { get; set; }
public object _9338 { get; set; }
public string _111 { get; set; }
}
This look's ok but In my case those JSON files have dynamic property names and can have another "int" values. Also the nested content inside "49" can have less or more values.
I am especially interested in gathering "49" << this value to variable.
I also have tried something like this, but doesn't work either:
public class DeserializeJsonContent
{
public Dictionary<object, Dictionary<object, object>> values { get; set; }
}
Simplified code sample
public List<T> JSONDeserialize<T>(IRestResponse response) where T : new()
{
var responseData = client.Deserialize<List<T>>(response);
var ListDeserializedData = responseData.Data.ToList<T>();
return ListDeserializedData;
}
....
var response = rest.client.Execute(request);
if (response.IsSuccessful)
{
var obj = rest.JSONDeserialize<DeserializeJsonContent>(response);
}
obj has count 1 but vals = null
Edit after Solve:
I still have no idea why my deserialized class doesn't work in this case (I am using it in many other json deserialization response's)
Thanks to xdtTransform answer I have tried and all of those worked
var obj2 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<object, object>>>(response.Content);
var obj3 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(response.Content);
var obj4 = JsonConvert.DeserializeObject<Dictionary<int, Dictionary<string, string>>>(response.Content);
var obj5 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<string, string>>>(response.Content);
var obj6 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<object, object>>>(response.Content);
var obj7 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<int, object>>>(response.Content);
Then just
var value = obj2.First().Key;

Using Newtonsoft.Json, You can directly deserialize to Dictionary<string,Dictionary<string,string>> like :
var obj = JsonConvert.DeserializeObject<Dictionary<string,Dictionary<string,string>>>(input);
If you need it to be in your custom type, you should declare this type like :
public class WrapperType : Dictionary<string,Dictionary<string,string>>{}
Then the Deserialisation stay the same:
var obj = JsonConvert.DeserializeObject<WrapperType>(input);
Updated demo

Please deserialize response content
string data = response.Content;
var responseData = client.Deserialize<List<T>>(data);

Related

Trouble while deserializing multidimentional json object in c# using JsonConvert.DeserializeObject

I am deserializing an json object with JsonConvert.DeserializeObject
object is like this:
"journalItemAccounts":"{\"item1\":\"2222\"}"
My deserialize code is:
jsonResult.accountsData.journalItemAccounts != null ? JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonResult.accountsData.journalItemAccounts) : null;
jsonResult.accountsData.journalItemAccounts contains "journalItemAccounts":"{\"item1\":\"2222\"}"
This is deserializing perfectly. But what if i need to deserialize the object like this:
"journalItemAccounts":"{\"item1\":{\"incomeAccount\":\"5030\",\"expenseAccount\":\"\",\"assetAccount\":\"\"}}"
You can start DeserializeObject with Dictionary<string, object> and check whether the value is Object or Value. Here is the example method to convert the Json to pick the value or object
public class item1
{
public string incomeAccount { get; set; }
public string expenseAccount { get; set; }
public string assetAccount { get; set; }
}
public static void ParseJson(string json)
{
var keyValuePairs = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
foreach (var keyvaluepair in keyValuePairs)
{
var obj = keyvaluepair.Value.ToString();
decimal itemvalue;
if (decimal.TryParse(obj, out itemvalue))
{
Console.WriteLine(itemvalue);
}
else
{
var result = JsonConvert.DeserializeObject<item1>(obj);
Console.WriteLine($"{ result.incomeAccount } - {result.expenseAccount} - {result.assetAccount}");
}
}
}
Call this method to get the desired result
ParseJson("{\"item1\":\"2222\"}");
ParseJson("{\"item1\":{\"incomeAccount\":\"5030\",\"expenseAccount\":\"5031\",\"assetAccount\":\"0532\"}}");
Output
2222
5030 - 5031 - 0532
Create a type and pass that like this.
var deserializedObject = JsonConvert.DeserializeObject<Model>(jsonResult.accountsData.journalItemAccounts);
public class Model
{
public AnotherModel item1 { get; set; }
}
public class AnotherModel
{
public string incomeAccount { get; set; }
public string expenseAccount { get; set; }
public string assetAccount { get; set; }
}
You are getting this because you are using string as value. You use an Object type or a class instead.
jsonResult.accountsData.journalItemAccounts != null ? JsonConvert.DeserializeObject<Dictionary<string, Object>>(jsonResult.accountsData.journalItemAccounts) : null;

Deserialize JSON object in C#

I want to get manuscript summary from PubMed. The content of each summary is in a JSON with the following format. The "29498802" is a unique ID, and it is different for each manuscript.
{
"header":{
"type":"esummary",
"version":"0.3"
},
"result":{
"uids":[
"29498802"
],
"29498802":{
"uid":"29498802",
"pubdate":"2018 Mar 2",
"epubdate":"2018 Mar 2",
...
}
}
}
I use Newtonsoft.Json in C# to deserialize the JSON to an class:
var summary = JsonConvert.DeserializeObject<Summary>(stringResult);
My Summary class is as follows:
public class Summary
{
[JsonProperty("header")]
public Header header { get; set; }
[JsonProperty("result")]
public Result result { get; set; }
}
public class Result
{
[JsonProperty("uids")]
public List<string> uids { get; set; }
public Dictionary<string, PubMedId> content { get; set; }
}
public class PubMedId
{
[JsonProperty("uid")]
public string uid { get; set; }
...
}
I was able to extract "header (type and version)", "uids", but "content" is always null. Any suggestions?
var summary = JsonConvert.DeserializeObject<Summary>(text);
var resultjO = JObject.Parse(text).Value<JObject>("result");
var pubdAsJObject = resultjO.Value<JObject>(summary.result.uids[0]);
var pubMed = JsonConvert.DeserializeObject<PubMedId>(pubdAsJObject.ToString());

How do I deserialize a JSON array(flat) and ignore some token

I have this response from server
[{
"sys_id": "******************************",
"dv_model_id": "*****************",
"due": "YYYY-MM-DD HH:mm:ss",
"assigned_to": "1524s32a54dss412s121s",
"dv_assigned_to": "username",
"assigned_to.phone": "+12345678910",
"assigned_to.email": "abc#a.c",
"u_borrower_id": "fb36e45f0a12452004742183457e833b0",
"dv_u_borrower_id": "antoherUserName",
"u_borrower_id.phone": "+12345678910",
"u_borrower_id.email": "abcf#a.c"
}
,{....}
,{....}]
I'm trying to deserialize this to List
public class Inventory
{
public Inventory()
{
assigned_to = new User();
u_borrower_wwid = new User();
}
public string sys_ID { get; set; }
public string dv_model_id { get; set; }
public DateTime due { get; set; }
public string dv_assigned_to { get; set; }
public User assigned_to { get; set; }
public string dv_u_borrower_id { get; set; }
public User u_borrower_id { get; set; }
}
now, since the JSON contains - "assigned_to": "1524s32a54dss412s121s","
the deserialization failed.
the same with the - ""u_borrower_id": "fb36e45f0a12452004742183457e833b0"," .
do you know any way to ignore them? or remove them from the JSON?
I need only the properties (".phone" and ".email") of the object.
any ideas?
I see a number of solutions:
Modify your Inventory object (or create a new one) so the json can be fully deserialized, then access the values there.
Your new and updated object should look like this:
public class InventoryJsonObject
{
public string sys_id { get; set; }
public string dv_model_id { get; set; }
public string due { get; set; }
public string assigned_to { get; set; }
public string dv_assigned_to { get; set; }
[JsonProperty("assigned_to.phone")]
public string assigned_to_phone { get; set; }
[JsonProperty("assigned_to.email")]
public string assigned_to_email { get; set; }
public string u_borrower_id { get; set; }
public string dv_u_borrower_id { get; set; }
[JsonProperty("u_borrower_id.phone")]
public string u_borrower_id_phone { get; set; }
[JsonProperty("u_borrower_id.email")]
public string u_borrower_id_email { get; set; }
}
Use regular expressions to get the values from the string. In this case your regex would be "u_borrower_id\.phone": "(.*?)" and "u_borrower_id\.email": "(.*?)"
The complete regex solution could look like this (assuming every object has a phone and email included):
string phonePattern = "\"u_borrower_id\\.phone\": \"(.*?)\"";
string emailPattern = "\"u_borrower_id\\.email\": \"(.*?)\"";
Regex phoneRegex = new Regex(phonePattern);
var phoneMatches = phoneRegex.Matches(input);
Regex emailRegex = new Regex(emailPattern);
var emailMatches = emailRegex.Matches(input);
for (int i = 0; i < phoneMatches.Count; i++)
{
string phoneMatch = phoneMatches[i].Groups[1].Value;
string emailMatch = emailMatches[i].Groups[1].Value;
// Now you can add them to any collection you desire
}
Implement a cast between string and User. Since your error originates from the fact that the string fb36e45f0a12452004742183457e833b0 cannot be cast into a User object trivially, you have to implement the cast. It would look like this:
public static implicit operator User(string _string)
{
// This could be a DB lookup, or basically anything else
return new User()
{
id = _string
};
}
In order to avoid unnecessary casting that causes bug you can use this workaround by creating a Dictionary<string, object>
and read only the properties you need as strings and convert them to your desired type:
using System.Web.Script;
Dictionary<string, object> dict = Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Now you can modify your class properties one by one like:
(You can create additional method for your DateTime and User property)
Inventory inventory = new Inventory();
//notice i'v added the 'u_borrower_id_email' property to your class:
inventory.u_borrower_id_email = dict.GetStringOrDefault("u_borrower_id.phone");
private static string GetStringOrDefault(this Dictionary<string, object> data, string key)
{
string result = "";
object o;
if (data.TryGetValue(key, out o))
{
if (o != null)
{
result = o.ToString();
}
}
return result;
}

Add root element to json serialization in C#

I am creating a webservice to interact with a JSON API.
This API needs me to set a root element in the string, but I just cannot get this to happen.
The place where it all happens - right now just made to just show me the json output:
public static string CreateServiceChange(ServiceChange change)
{
string json = JsonConvert.SerializeObject(change);
return json;
}
This is the ServiceChange class:
public class ServiceChange
{
[JsonProperty("email")]
public string requesterEmail { get; set; }
[JsonProperty("description_html")]
public string descriptionHtml { get; set; }
[JsonProperty("subject")]
public string subject { get; set; }
[JsonProperty("change_type")]
public int changeType { get; set; }
}
And the method binding those two together:
public string copyTicketToChange(int ticketId)
{
HelpdeskTicket.TicketResponseActual ticket = getHelpdeskTicket(ticketId);
ServiceChange change = new ServiceChange();
change.descriptionHtml = ticket.Response.DescriptionHtml;
change.requesterEmail = ticket.Response.Email;
change.subject = ticket.Response.Subject;
change.changeType = 1;
string Response = Dal.CreateServiceChange(change);
return Response;
}
The json output looks like this right now:
{"email":"test#test.com","description_html":"This is a test","subject":"Testing","change_type":1}
And the expected output:
{ "itil_change": {"email":"test#test.com","description_html":"This is a test","subject":"Testing","change_type":1}}
How can I achieve this?
Wrap your ServiceChange into another object and serialize it:
public class ServiceChangeWrapper
{
public ServiceChange itil_change { get; set; }
}
...
public static string CreateServiceChange(ServiceChange change)
{
ServiceChangeWrapper wrapper = new ServiceChangeWrapper { itil_change = change};
string json = JsonConvert.SerializeObject(wrapper);
return json;
}

Overriding .NET MVC's automatic JSON deserialization with ServiceStack

I'm trying to implement usage of ServiceStack for faster JSON serialization/deserialization in my .NET MVC4 application.
I have following for deserializing AJAX requests:
Global.asax.cs:
// Remove and JsonValueProviderFactory and add JsonServiceStackValueProviderFactory
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonServiceStackValueProviderFactory());
public sealed class JsonServiceStackValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return null;
var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream).BaseStream;
return new DictionaryValueProvider<object>(
ServiceStack.Text.JsonSerializer.DeserializeFromStream<Dictionary<string, object>>(reader).AsExpandoObject(),
CultureInfo.CurrentCulture);
}
}
// http://nine69.wordpress.com/2013/02/02/asp-net-mvc-series-high-performance-json-parser-for-asp-net-mvc/
public static class CollectionExtensions
{
public static ExpandoObject AsExpandoObject(this IDictionary<string, object> dictionary)
{
var epo = new ExpandoObject();
var epoDic = epo as IDictionary<string, object>;
foreach (var item in dictionary)
{
bool processed = false;
if (item.Value is IDictionary<string, object>)
{
epoDic.Add(item.Key, AsExpandoObject((IDictionary<string, object>) item.Value));
processed = true;
}
else if (item.Value is ICollection)
{
var itemList = new List<object>();
foreach (object item2 in (ICollection) item.Value)
if (item2 is IDictionary<string, object>)
itemList.Add(AsExpandoObject((IDictionary<string, object>) item2));
else
itemList.Add(AsExpandoObject(new Dictionary<string, object> {{"Unknown", item2}}));
if (itemList.Count > 0)
{
epoDic.Add(item.Key, itemList);
processed = true;
}
}
if (!processed)
epoDic.Add(item);
}
return epo;
}
}
I am trying to deserialize an object which looks like:
[DataContract]
public class PlaylistItemDto
{
[DataMember(Name = "playlistId")]
public Guid PlaylistId { get; set; }
[DataMember(Name = "id")]
public Guid Id { get; set; }
[DataMember(Name = "sequence")]
public int Sequence { get; set; }
// Store Title on PlaylistItem as well as on Video because user might want to rename PlaylistItem.
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "video")]
public VideoDto Video { get; set; }
[DataMember(Name = "cid")]
public string Cid { get; set; }
public PlaylistItemDto()
{
Id = Guid.Empty;
Title = string.Empty;
}
public static PlaylistItemDto Create(PlaylistItem playlistItem)
{
PlaylistItemDto playlistItemDto = Mapper.Map<PlaylistItem, PlaylistItemDto>(playlistItem);
return playlistItemDto;
}
public static List<PlaylistItemDto> Create(IEnumerable<PlaylistItem> playlistItems)
{
List<PlaylistItemDto> playlistItemDtos = Mapper.Map<IEnumerable<PlaylistItem>, List<PlaylistItemDto>>(playlistItems);
return playlistItemDtos;
}
}
[DataContract]
public class VideoDto
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "duration")]
public int Duration { get; set; }
[DataMember(Name = "author")]
public string Author { get; set; }
[DataMember(Name = "highDefinition")]
public bool HighDefinition { get; set; }
public VideoDto()
{
Id = string.Empty;
Title = string.Empty;
Author = string.Empty;
}
/// <summary>
/// Converts a Domain object to a DTO
/// </summary>
public static VideoDto Create(Video video)
{
VideoDto videoDto = Mapper.Map<Video, VideoDto>(video);
return videoDto;
}
public static List<VideoDto> Create(IEnumerable<Video> videos)
{
List<VideoDto> videoDtos = Mapper.Map<IEnumerable<Video>, List<VideoDto>>(videos);
return videoDtos;
}
}
The first level is deserialized correctly, but the Video object is null. I have been scouring the web for additional documentation, but haven't come up with much. I've found these articles which seem to be relevant:
How to get ServiceStack to serialize / deserialize an expando object with correct types
Deserializing JSON into Object
But the first doesn't provide an example -- only mentions some changes to the new versions of ServiceStack. The second shows how to deserialize, but doesn't handle a Stream or ExpandoObjects. The first hints that ExpandoObjects might not be fully supported.
I feel like I am trying to deserialize a pretty simple object. Is there any support for nested levels of objects in ServiceStack? Thanks
You can see full source on GitHub if that is helpful: https://github.com/MeoMix/StreamusServer/blob/development/Streamus/Global.asax.cs

Categories