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
Related
I'm trying to write a generic method which will deserialize JSON responses. In the end, I am getting an error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[ClientAddressWFA.Models.Address]' 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.
Here is the code of the method below 👇
public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(uri);
var content = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(content);
JsonReader jReader = new JsonTextReader(reader);
JsonSerializer jSer = new JsonSerializer();
return jSer.Deserialize<IEnumerable<T>>(jReader);
}
This is the schema of the API response:
And this is the model. I'm using IEnumerable collection of type Address model to store desirialized data:
public class Address
{
[JsonProperty("id")]
public int Id;
[JsonProperty("streetAddress")]
public int StreetAddress;
[JsonProperty("streetName")]
public string StreetName;
[JsonProperty("buildingNumber")]
public int BuildingNumber;
[JsonProperty("additionalBuildingNumber")]
public string AdditionalBuildingNumber;
[JsonProperty("fullAddress")]
public string FullAddress;
[JsonProperty("zipCode")]
public int ZipCode;
[JsonProperty("coordinateX")]
public double CoordinateX;
[JsonProperty("coordinateY")]
public double CoordinateY;
[JsonProperty("sozraum")]
public int Sozraum;
[JsonProperty("sozialraum")]
public int Sozialraum;
[JsonProperty("lebraum")]
public int Lebraum;
[JsonProperty("lebensraum")]
public int Lebensraum;
[JsonProperty("stimmbezirk")]
public int Stimmbezirk;
[JsonProperty("hnr_nur_fb62")]
public string HnrNurFb62;
[JsonProperty("gerade")]
public string Gerade;
[JsonProperty("district")]
public string District;
[JsonProperty("districtNumber")]
public string DistrictNumber;
[JsonProperty("wkb_geometry")]
public string WkbGeometry;
[JsonProperty("isMain")]
public bool IsMain;
}
The JSON response you're getting has the addresses array nested within a higher-level object. The simplest solution would be to create that high-level response object:
public class Response<T> {
public List<T> Data {get; set;}
public bool Success {get;set;}
public string Message {get;set;}
}
You can then deserialize the Response object in your method and return just the data property from it:
public static async Task<IEnumerable<T>> JsonDeserialize<T>(string uri) {
//...all the code up until deserialization
return jSer.Deserialize<Response<T>>(jReader).Data;
}
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);
}
I am receiving a JSON string back from an API and want to deserialize it into C# objects but cannot get the classes correct.
I have tried creating the classes using http://json2csharp.com/ but it can't parse the JSON, however https://jsonlint.com/ says that the JSON is valid.
I also tried running JsonClassGeneratorLib but that says
Unable to cast object of type Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject
It seems to be an issue because the JSON is enclosed in [] square brackets. I believe this is valid but makes it into an array. I think I need an array somewhere in my class.
string Json = #"[""error"",{""code"":2,""msg"":""This API Key is invalid""}]";
var obj = JsonConvert.DeserializeObject<RootObject>(Json);
public class CodeMsg
{
[JsonProperty("code")]
public long Code { get; set; }
[JsonProperty("msg")]
public string Msg { get; set; }
}
public class Result
{
[JsonProperty("error")]
public string String { get; set; }
public CodeMsg cm { get; set; }
}
public class RootObject
{
public Result Result { get; set; }
}
I always get the error
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ConsoleApp1.RootObject' 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
Try this:
var obj = JsonConvert.DeserializeObject<List<Result>>(Json);
Explanation: If the JSON is an Array, the C# RootObject has to be either deriving from List/IEnumerable itself, or you deserialize it to a List/Array of the Type.
You can dump your RootObject class. If you wanted to use the RootObject type, make it derive from List. But this is not worth the hassle.
Your JSON is a heterogeneous array containing a string and an object. This will not deserialize cleanly into a strongly-typed class structure without a little help. One possible solution is to use a custom JsonConverter like this:
public class ResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Result);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
Result result = new Result
{
String = array[0].Value<string>(),
cm = array[1].ToObject<CodeMsg>(serializer)
};
return result;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then tie the converter to your Result class with a [JsonConverter] attribute like this:
[JsonConverter(typeof(ResultConverter))]
public class Result
{
public string String { get; set; }
public CodeMsg cm { get; set; }
}
Finally, deserialize the JSON into the Result class like this:
var result = JsonConvert.DeserializeObject<Result>(Json);
Working demo: https://dotnetfiddle.net/RLpm5W
Note: You can delete the RootObject class; it is not needed here.
Just make sure, your json string must have same properties as JsonHolder class.
public class JsonHolder
{
public string Id {get;set;}
public string Name {get;set;}
public string Gender {get;set;}
}
var jsonHolderList = new JsonConvert.DeserializeObject<List<JsonHolder>>(jsonString);
var jsonHolder = jsonHolderList.Single()
You can also convert json string into c# object as dynamic object. Just make sure, your json string must have same properties as JsonHolder class.
dynamic obj= new JsonConver.DeserializeObject<List<JsonHolder>>(StrJson);
Let's say I have a Value that is deserialized from a class.
public class MyValue
{
public string MyPropertyA { get; set; }
public string MyPropertyB { get; set; }
public string DeserializationClass { get; } = typeof(MyValue).Name;
}
I serialize this using JsonConvert class. MyValue class has a property DeserializationClass that should be used as info from which class the string was serialized from. In other words, when I deserialize the string into an object, this property serves as info which class should be used to deserialize the string. However, I am kinda stuck here as I am not sure how to get back the class from the string. Can anybody help me here?
public class Program
{
void Main()
{
var serialized = Serialize();
var obj = Deserialize(serialized);
}
string Serialize()
{
var objValue = new MyValue { MyPropertyA="Something", MyPropertyB="SomethingElse" };
return JsonConvert.SerializeObject<MyClass>(value);
}
object Deserialize(string serialized)
{
//How to deserialize based on 'DeserializationClass' property in serialized string?
return = JsonConvert.Deserialize<???>(serialized);
}
}
EDIT: Modified example to make it more clear what I need as I don't have access to objValue when I need to deserialize the string.
probably you might need to use JsonSerializerSettings.
What you might need to do is
JsonSerializerSettings setting = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
};
and then while serializing use this setting.
var serialized = JsonConvert.SerializeObject(objValue,setting);
this will give you Json like this
{"$type":"WPFDatagrid.MyValue, WPFDatagrid","MyPropertyA":"Something","MyPropertyB":"SomethingElse","DeserializationClass":"MyValue"}
from this you can find the name of the class used it to actually get your type.
Hope this helps !!
There is an overload
If your Type is in form of a Namespace, you can obtain the type from a string representation:
Type objValueType = Type.GetType("Namespace.MyValue, MyAssembly");
object deserialized = JsonConvert.Deserialize(objValueType, serialized);
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\":{}");