Deserialize arbitrary JSON object with JSON.NET - c#

I want to deserialize a JSON strin like this
{
"status":"1",
"since":"1245626956',
"list":{
"1":{
"item_id":"1"
},
"2":{
"item_id":"2"
}
}
}
For this I have an object that parses that
public class ListResponse
{
public String status { get; set; }
public String since { get; set; }
public IDictionary<String, Item> list { get; set; }
}
I use this sentence:
ListResponse list = JsonConvert.DeserializeObject<ListResponse>(message);
That works well but I have a problem because response can be something like this
{
"status":"1",
"since":"1245626956',
"list":[]
}
When trying to deserialize that an exception raises because needs an array to parse 'list' but my object has a IDictionary.
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.IDictionary`2[System.String,Item]' 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.
How can I handle this issue without using Linq to obtain JObject and do the mapping "by hand"?

A simple workaround would be to do this before deserializing:
yourString = yourString.Replace("\"list\":[]", "\"list\":{}");

Related

JsonSerializationException how to solve

I have been trying deserialiable the api and the program shows this error: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[System.Diagnostics.Activity]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'activity', line 1, position 12.'
This is my code:
enter image description here
enter image description here
thanks if someone can help me
if your json data looks like this :
jsonData = [{"id":"518523721","name":"ftyft"},
{"id":"527032438","name":"ftyftyf"},
{"id":"527572047","name":"ftgft"},
{"id":"531141884","name":"ftftft"}]
then you can try :
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
}
var people = JsonConvert.DeserializeObject<List<Person>>(json);
in case of array format :
public class PersonArray
{
public Pserson[] Person{get;set;}
}
var people = JsonConvert.DeserializeObject<PersonArray>(json);

Serialize and deserialize an IEnumerable in Session

I have this method:
public static class SessionExtension
{
public static void SetObjectAsJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObjectFromJson<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
}
Which is useful to serialize my list of IEnumerable:
public IEnumerable<FBudget> RecordsList { get; set; }
So after filtering the data I serialize the object:
//BUILD FILTER
static Expression<Func<FBudget, bool>> BuildFilter(BudgetViewModel budget)
{
...
}
/*STORE THE ACTUAL FILTER IN SESSION*/
SessionExtension.SetObjectAsJson(HttpContext.Session, "SessionFilter", budget);
An the deserialize it:
public IActionResult Index()
{
var json = SessionExtension.GetObjectFromJson<IEnumerable<FBudget>>(HttpContext.Session, "SessionFilter");
BudgetVM = new BudgetViewModel()
{
FBudget = new FBudget(),
...
RecordsList = json
};
return View(BudgetVM);
}
But when I try to deserialize it, the compiler give the the following error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[...]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'FBudget', line 1, position 11.'
Also I'm trying to do this in order to keep in session the result of the BuildFilter() method, so when the user return to a previous page the filters are saved.
Is the correct approach? What am I doing wrong?
This is the Json which is sendend to the method GetObjectFromJson:
{"BudgetId":0,"Year":0,"FreeOfCharge":null,"Currency":null,"UnitPrice":0.0,"MonthNr":null,"UnitOfMeasure":null,"Quantity":0,"TotalAmount":0.0,"LastUser":null,"ProgramId":0,"LastUpdate":"2021-11-03T15:08:15.65645+01:00","ItemMasterId":0,"ItemMaster":{"ItemMasterId":0,"ItemNumber":0,"ShortItem":null,"ItemDescription":null,"UnitOfMeasure":null,"FBudgets":null,"PharmaFormId":0,"PharmaForm":null,"ProductGroupId":0,"ProductGroup":null,"UnToBulkId":0,"UnToBulk":null,"UnToKgId":0,"UnToKg":null},"CompanyId":2,"Company":null,"LedgerTypeId":0,"LedgerType":null,"CustomerId":0,"Customer":{"CustomerId":0,"CustomerName":null,"CustomerGroupCode":null,"CountryCode":null,"CustomerGroupName":null,"LicensingArea":null,"FBudgets":null}}
Since your mentioned json is an object not an array, for deserialize try the below code:
public IActionResult Index()
{
var json = SessionExtension.GetObjectFromJson<FBudget>(HttpContext.Session, "SessionFilter");
BudgetVM = new BudgetViewModel()
{
FBudget = new FBudget(),
...
RecordsList = new List<FBudget> { json }
};
return View(BudgetVM);
}

JSON array to Dictionary

I'm trying to deserialize JSON to C# object using NewtonsoftJson.
My json looks like this:
{"something" : [ "key1" : "value1", "key2" : "value2"]}
But it's not a full json. So it should be kind of part of large object.
I can't use this solution JSON array to C# Dictionary
because I use
JsonConvert.DeserializeObject<MyObject>(json);
Does it possible to initialize object like this?
public class Something
{
[JsonProperty]
public Dictionary<string, string> MyDictionary;
}
But when I'm trying to do that I get exception:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'System.Collections.Generic.Dictionary`2[System.String,ConsoleApp4.TxPerfMeasurements]'
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 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.
Input
{
"something": [
{ "key1": "value1" },
{ "key2": "value2" }
]
}
Your model should look like below
public class Something
{
public List<Dictionary<string, string>> something { get; set; }
}
Use Linq to convert to Dictionary
var result = JsonConvert.DeserializeObject<Something>(json);
var dict = result.something.SelectMany(d => d).ToDictionary(e => e.Key, e => e.Value);
Output

Saving json array to c# class object

I have to assign json array of string to a c# class. I have done like below. But I got an exceptio
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'LoggedInUserDetails' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo 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 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.\r\nPath '', line 1, position 1."}
public class LoggedInUserDetails
{
public string login_user_name
{
get; set;
}
public string login_user_id
{
get; set;
}
}
var GetResponse = await response2.Content.ReadAsStringAsync();
//"[{\"login_user_name\":\"Rahul\",\"login_user_id\":\"43\"}]"
LoggedInUserDetails obj = JsonConvert.DeserializeObject<LoggedInUserDetails>(GetResponse);
Variables.login_user_name = obj.login_user_name;
Variables.login_user_id= obj.login_user_id;
You should deserialize the json string to an IEnumerable collection or Array.
var content = await response2.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<List<LoggedInUserDetails>>(content);
It because of the '[]', which stores it as a array of results. You should be able to do something like the following:
LoggedInUserDetails obj = JsonConvert.DeserializeObject<List<LoggedInUserDetails>>(GetResponse);
where you try to deserialize object as an list. The list will only contain 1 object.
full example:
public class LoggedInUserDetails
{
public string login_user_name
{
get; set;
}
public string login_user_id
{
get; set;
}
}
var GetResponse = await response2.Content.ReadAsStringAsync();
//"[{\"login_user_name\":\"Rahul\",\"login_user_id\":\"43\"}]"
List<LoggedInUserDetails> obj = JsonConvert.DeserializeObject<List<LoggedInUserDetails>>(GetResponse);
Variables.login_user_name = obj[0].login_user_name;
Variables.login_user_id= obj[0].login_user_id;
This way:
LoggedInUserDetails obj = JsonConvert.DeserializeObject<LoggedInUserDetails[]>(GetResponse).FirstOrDefault() ?? throw new Exception("User not found.");
Variables.login_user_name = obj.login_user_name;
Variables.login_user_id = obj.login_user_id;
Your result was an array containing 1 object, so you just had to convert it to an array of your desired object and take the first.
Since you are using array, then it should deserialize array to list
public class Test
{
public string login_user_name {get; set;}
public string login_user_id { get; set;}
}
string js = "[{\"login_user_name\":\"Rahul\",\"login_user_id\":\"43\"}]";
var result = JsonConvert.DeserializeObject<List<Test>>(js);
foreach(var ob in result)
{
Console.WriteLine(ob.login_user_name);
Console.WriteLine(ob.login_user_id);
}
output
Rahul
43

Unable to Serialize JSON to Dictionary

I have an issue with JSON serialization into a class with a dictionary property.
The whole process is a bit more complex, as an input i have a YAML file that i convert into a json using YamlDotNet and NewtonSoft like so
This is an example of the Yaml and the JSON output
some_element: '1'
should_be_dic_element:
- a: '1'
- b: '2'
{
"some_element": "1",
"should_be_dic_element": [
{
"a": "1"
},
{
"b": "2"
}
]
}
And the class
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public Dictionary<string, string> Dictionary { get; set; }
}
I know the issue with Array dictionary so this are all the things I've tried.
Using Dictionary i get the following
error Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' 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 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
Using a new class from Dictionary like so
[JsonArray]
class X : Dictionary<string, string> { }
error Value cannot be null.
Parameter name: key
Using KeyValuePair<string, string>[] / List<KeyValuePair<string, string>> the outcome is the amount of elements but with null values.
Any suggestions please ?
I think your JSON which you are attempting to de-serialize is not conforming to your class definition. Try changing the way you are generating the JSON.
For a dictionary-type structure, I would expect to see curly braces { instead of [ to begin the structure, e.g.:
{
"some_element": "1",
"should_be_dic_element": {
{
"a": "1"
},
{
"b": "2"
}
}
}
If you want to deserialize the existing JSON unchanged, try using your class definition to specify a list of dictionaries as such:
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public List<Dictionary<string, string>> Dictionary { get; set; }
}

Categories

Resources