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;
Related
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);
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;
}
Currently I am just returning the json string to corresponding file from where Test1() is called and Deserializing there as ResponseClass r = JsonConvert.DeserializeObject(response_json)
Send part I forget to make a class [Serializable].Its working fine now.
Part1:
public class Movie
{
public string Name { get; set; }
public string Description { get; set; }
public string Classification { get; set; }
public string Studio { get; set; }
public DateTime? ReleaseDate { get; set; }
public List<string> Genres{ get; set; }
}
public class ResponseClass
{
public string SuccessStatus{ get; set; }
public string next_link { get; set; }
}
private void Test1<T,Q>()
{
string json = #"{
'Name': 'Bad Boys',
'ReleaseDate': '1995-4-7T00:00:00',
'Genres': [
'Action',
'Comedy'
]
}";
//Here making network call with above json and getting correct response_josn
Q response_obj = JsonConvert.DeserializeObject<Q>(reponse_json);
print(response_obj);
}
I am calling Test1() as follows on button click:
Test1<Movie, ResponseClass>();
For the above example I am getting print log as ClassName+Movie (T FullName).
I want to deserialize the string into that class. How to achieve that?
Part2 : If I have class as:
[Serializable]
public class Movie
{
public string Name;
public string Description;
public string Classification;
public string Studio;
public DateTime ReleaseDate;
public SubClass subClass;
public List<SubClass> lsubclass;
}
[Serializable] //This was the mistake.
public class SubClass
{
public string a;
public string b;
public List<string> ReleaseCountries;
}
private Movie createValidMovieJson()
{
Movie m = new Movie();
SubClass sc = new SubClass();
sc.a = "aaa";
sc.b = "bbb";
sc.ReleaseCountries = new List<string>();
sc.ReleaseCountries.Add("Japan");
sc.ReleaseCountries.Add("India");
List<SubClass> lsC = new List<SubClass>();
lsC.Add(sc);
lsC.Add(sc);
m.Name = "Bad Boys";
m.Studio = "Pixa";
m.subClass = sc;
m.lsubclass = lsC;
Debug.Log(JsonUtility.ToJson(m)); // value n log = {"Name":"Bad Boys","Description":"","Classification":"","Studio":"Pixa"}
return m;
}
JsonUtility is returning empty value in place of subclass after using ToJson() as shown in above function.
Based on the screenshot you added I think you are expecting to be able to treat the deserialized type as a Movie. This is the way to achieve that:
var movie = JsonConvert.DeserializeObject<Movie>(json);
Currently your deserialized object is being treated as type T - which could be anything since you have no generic type constraints on your method.
Like I said in the comment section, JsonUtility should do it.
I just replaced T m = JsonConvert.DeserializeObject(json); with T
m = JsonUtility.FromJson(json); it gives an error
ArgumentException: JSON parse error: Missing a name for object member.
Your json is invalid for JsonUtility. I believe you are using ' instead of ". This is why you are getting this error.
Use the function below to generate a valid json:
void createValidMovieJson()
{
Movie m = new Movie();
m.Name = "Bad Boys";
m.ReleaseCountries = new List<string>();
m.ReleaseCountries.Add("Japan");
m.Studio = "Pixa";
Debug.Log(JsonUtility.ToJson(m));
}
You will get:
{"Name":"Bad Boys","Description":"","Classification":"","Studio":"Pixa","ReleaseCountries":["Japan"]}
When ecaped for testing, you will get:
{\"Name\":\"Bad Boys\",\"Description\":\"\",\"Classification\":\"\",\"Studio\":\"Pixa\",\"ReleaseCountries\":[\"Japan\"]}
For JsonUtility to work, you must add [Serializable] to the class and remove { get; set; } from them class variables.
If your goal is to convert any json to any data type then you have to return generic type then use Convert.ChangeType to convert it to that type.
It should look something like this:
// Use this for initialization
void Start()
{
string json = "{\"Name\":\"Bad Boys\",\"Description\":\"\",\"Classification\":\"\",\"Studio\":\"Pixa\",\"ReleaseCountries\":[\"Japan\"]}";
Movie movie = Load<Movie>(json);
print(movie.Name);
}
[Serializable]
public class Movie
{
public string Name;
public string Description;
public string Classification;
public string Studio;
public DateTime? ReleaseDate;
public List<string> ReleaseCountries;
}
private T Load<T>(string json)
{
object resultValue = JsonUtility.FromJson<T>(json);
return (T)Convert.ChangeType(resultValue, typeof(T));
}
I have a class with a dynamic member. When the value is a boolean, it's serialized as true / false which deserializes to a string. Is this an issue with YamlDotNet, or if not, how can I force it to serialize as true rather than "true"?
This is a class I'm trying to serialize
public class Field : IField
{
public string MachineName { get; set; }
public string DisplayName { get; set; }
public FieldFormatterEnum FormatterType { get; set; }
public dynamic Value { get; set; }
public dynamic DefaultValue { get; set; }
public dynamic FormattedValue { get; set; }
...
}
The typed deserializer method:
public T DeserializeObject<T>(string input)
{
T o;
using (var tr = new StringReader(input))
{
o = new Deserializer().Deserialize<T>(tr);
}
return o;
}
Field is in a List in another class which is being serialized / deserialized.
Update: After looking at the serialized output, YamlDotNet outputs the serialized boolean as true and not "true". So.. I'm guessing it's a problem with the deserialization code in YamlDotNet?
For serialization, you could create a getter-only property as a bool that has the value you want:
public bool ValueAsBool
{
get
{
bool outValue = false;
if(Value is string)
{
bool.TryParse((string)Value, out outValue);
return outValue;
}
return outValue;
}
}
Ultimately, when working with dynamics you will be throwing some type information away, and you shouldn't expect to be able to recover all of it properly.
I've just set up a simple test like:
class Foo
{
public dynamic V { get; set; }
}
var f1 = new Foo(){V = 5};
var tw2 = new StringWriter();
new Serializer().Serialize(tw2, f1);
var tr2 = new StringReader(tw2.ToString());
var f_1 = new Deserializer().Deserialize<Foo>(tr2);
... and V is deserialized as "5". The default type to deserialize to is string
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;
}