How I get data from json with linq? - c#

[
{
"id": "133",
"label": "S/M",
"price": "0",
"oldPrice": "0",
"products": [
"318",
"321",
"324",
"327"
]
},
{
"id": "132",
"label": "L/XL",
"price": "0",
"oldPrice": "0",
"products": [
"319",
"322",
"325",
"328"
]
},
{
"id": "131",
"label": "XXL/XXXL",
"price": "0",
"oldPrice": "0",
"products": [
"320",
"323",
"326",
"329"
]
}
]
I want to get 'label' where array "products" contains "321". How i can make this? I used library json.net
i make linq expression
JArray ja = JArray("this json");
JValue id = JValue.Parse("328");
ja.Select(x => x["label"]).Where(x => x["products"].Contains(id));
But i get "Cannot access child value on Newtonsoft.Json.Linq.JValue."

So you should define the class first:
class MyObj {
public string id { get; set; }
public string[] products { get; set; }
public string label { get; set; }
}
And deserialize that instead of object:
var deserialized = serializer.Deserialize<MyObj>(str);
var result = deserialized.Where(r => r.products.Contains("321")).ToList();

For this you can use any JSON library. e.g. JSON.NET
This LINQ to JSON sample

You need to use a library like JSON.NET.
In this case you can write something like this
string json = <your json string>;
var deserializedProduct = JsonConvert.DeserializeObject<List<Product>>(json).Where(p => p.products.Contains("321")).ToList();
where Product is
public class Product
{
public string id { get; set; }
public string[] products { get; set; }
public string label { get; set; }
}

Related

Netwonsoft JSON deserialize into List with named entries

I want to deserialize this JSON:
{
"Home1": [
{
"name": "Hans",
"age": 20
},
{...}
],
"Home2": [
{...},
{...}
]
}
into an List<House>
with these classes:
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
class House : List<Person> {
public string Name { get; set; }
}
How can I tell Newtonsoft JSON that House.Name should be for the key (Home1)?
PS: The class structure is not fixed, but I need the name of the house to be a property in a class.
Leaving behind the rational behind the idea of inheriting a list and your class structure you surely can create custom converter but I would argue much easier option would be to deserialize json into Dictionary<string, House> (which can represent your json structure) and then manually map the names:
var result = JsonConvert.DeserializeObject<Dictionary<string, House>>(json);
foreach (var kvp in result)
{
kvp.Value.Name = kvp.Key;
}
var houses = result.Values;
try this
var deserializedJson = JsonConvert.DeserializeObject<Dictionary<string, List<Person>>>(json);
var houses=new List<House>();
foreach (var element in deserializedJson)
{
houses.Add(new House { Name = element.Key, Persons = element.Value} );
}
var result=JsonConvert.SerializeObject(houses);
}
result
[
{
"Name": "Home1",
"Persons": [
{
"Name": "Hans",
"Age": 20
}
]
},
{
"Name": "Home2",
"Persons": [
{
"Name": "John",
"Age": 22
}
]
}
]
classes
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class House
{
public string Name { get; set; }
public List<Person> Persons {get; set;}
}
Json parsing/deserialization doesn't work this way.
You must have the class of same structure, of what the json is.
Your source json is object having property Home1, Home2 etc.
But you directly expecting it to convert into another structure.
I recommend first convert the json in Real object with the structure of json. Then loop through the property and fill it with loop in List.
Also can you please explain what this class is supposed to do.
class House : List<Person> { public string Name { get; set; } }
For me it doesn't make any sense.
An answer based on you requirement,
How about we clean your JSON string before deserializing and spicing it up with REGEX?
string json = #"{
""Home1"": [
{
""name"": ""Hans"",
""age"": 20
},
{
""name"": ""Hans"",
""age"": 20
},
],
""Home2"": [
{
""name"": ""Hans"",
""age"": 20
},
{
""name"": ""Hans"",
""age"": 20
},
]
}";
/*Replaces all Home + Digit combination to Home*/
json = Regex.Replace(json, #"Home\d*", "Home");
/* Output
{
"Home": [
{
"name": "Hans",
"age": 20
},
{
"name": "Hans",
"age": 20
},
],
"Home": [
{
"name": "Hans",
"age": 20
},
{
"name": "Hans",
"age": 20
},
]
}
*/

Converting Complex JSON to C# Model

I am trying to resolve the some complex JSON I am receiving to convert it to a C# Model so I can analyse and manipulate the data. I have tried converting the JSON by using JSON to C# but it doesn't work well when the name is dynamic. I want to focus on the Data.
The Item1 and SubItem1 etc are all variable strings so I can't hard code a model to pull them and the text is just a string within. The issue I am having is how to get the JSON into a usable format to access the Item1, SubItem1 and text values to manipulate their data.
I have looked into Dictionaries as suggested elsewhere but I am having no luck.
Model I have tried
public class Data
{
public string Status { get; set; }
public ResultInfo ResultInfo { get; set; }
public string Message { get; set; }
public Dictionary<string, SubData> Data {get;set;}
}
public class SubData
{
public Dictionary<string,List<string>> item {get;set;}
}
JSON
{
"Status": "OK",
"ResultInfo": {
"Prev": "PageUPURL",
"Next": "PageDownURL",
"total_count": "37",
"per_page": "3",
"page": "1"
},
"Message": "Ok.",
"Data": {
"Item1": [
{
"SubItem1": [
"Text"
]
}
],
"Item2": [
{
"SubItem2": [
"Text",
"Text",
"Text"
]
}
],
"Item3": [
{
"SubItem3": [
"Text"
]
},
{
"SubItem4": [
"Text"
]
}
]
}
}
Any suggestions, advice or help would be gratefully received.
For those task I use https://app.quicktype.io .
Because it can easly reconnize dictionary when the property name are numeric you just need to edit your Json a little.
And past it into the tool.
{
"Status": "OK",
"ResultInfo": {
"Prev": "PageUPURL",
"Next": "PageDownURL",
"total_count": "37",
"per_page": "3",
"page": "1"
},
"Message": "Ok.",
"Data": {
"1": [
{
"1": [
"Text"
]
}
],
"2": [
{
"1": [
"Text",
"Text",
"Text"
]
}
],
"3": [
{
"1": [
"Text"
]
},
{
"2": [
"Text"
]
}
]
}
}
The result class is :
public partial class Root
{
[JsonProperty("Status")]
public string Status { get; set; }
[JsonProperty("ResultInfo")]
public ResultInfo ResultInfo { get; set; }
[JsonProperty("Message")]
public string Message { get; set; }
[JsonProperty("Data")]
public Dictionary<string, List<Dictionary<string, List<string>>>> Data { get; set; }
}
public partial class ResultInfo
{
[JsonProperty("Prev")]
public string Prev { get; set; }
[JsonProperty("Next")]
public string Next { get; set; }
[JsonProperty("total_count")]
[JsonConverter(typeof(ParseStringConverter))]
public long TotalCount { get; set; }
[JsonProperty("per_page")]
[JsonConverter(typeof(ParseStringConverter))]
public long PerPage { get; set; }
[JsonProperty("page")]
[JsonConverter(typeof(ParseStringConverter))]
public long Page { get; set; }
}
Online Demo https://dotnetfiddle.net/1j42kR
nota bene: that tool also included a converter from "string" to "long" for "per_page": "3",
Change below line
public Dictionary<string, SubData> Data {get;set;}
as
public Dictionary<string, Dictionary<string, string[]>[]> Data { get; set; }

How can I deserialize Array of Arrays in Newtonsoft Json C#? [duplicate]

I have this JSON:
[
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 1",
"Values": [
"Acc 1"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "1",
"Values": [
"1"
]
}
}
],
"Name": "account",
"Id": "1"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 2",
"Values": [
"Acc 2"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "2",
"Values": [
"2"
]
}
}
],
"Name": "account",
"Id": "2"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 3",
"Values": [
"Acc 3"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "3",
"Values": [
"3"
]
}
}
],
"Name": "account",
"Id": "2"
}
]
And I have these classes:
public class RetrieveMultipleResponse
{
public List<Attribute> Attributes { get; set; }
public string Name { get; set; }
public string Id { get; set; }
}
public class Value
{
[JsonProperty("Value")]
public string value { get; set; }
public List<string> Values { get; set; }
}
public class Attribute
{
public string Key { get; set; }
public Value Value { get; set; }
}
I am trying to deserialize the above JSON using the code below:
var objResponse1 = JsonConvert.DeserializeObject<RetrieveMultipleResponse>(JsonStr);
but I am getting this error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'test.Model.RetrieveMultipleResponse' 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. Path
'', line 1, position 1.
Your json string is wrapped within square brackets ([]), hence it is interpreted as array instead of single RetrieveMultipleResponse object. Therefore, you need to deserialize it to type collection of RetrieveMultipleResponse, for example :
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
If one wants to support Generics (in an extension method) this is the pattern...
public static List<T> Deserialize<T>(this string SerializedJSONString)
{
var stuff = JsonConvert.DeserializeObject<List<T>>(SerializedJSONString);
return stuff;
}
It is used like this:
var rc = new MyHttpClient(URL);
//This response is the JSON Array (see posts above)
var response = rc.SendRequest();
var data = response.Deserialize<MyClassType>();
MyClassType looks like this (must match name value pairs of JSON array)
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class MyClassType
{
[JsonProperty(PropertyName = "Id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "Description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "Manager")]
public string Manager { get; set; }
[JsonProperty(PropertyName = "LastUpdate")]
public DateTime LastUpdate { get; set; }
}
Use NUGET to download Newtonsoft.Json add a reference where needed...
using Newtonsoft.Json;
Can't add a comment to the solution but that didn't work for me. The solution that worked for me was to use:
var des = (MyClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(MyClass));
return des.data.Count.ToString();
Deserializing JSON array into strongly typed .NET object
Use this, FrontData is JSON string:
var objResponse1 = JsonConvert.DeserializeObject<List<DataTransfer>>(FrontData);
and extract list:
var a = objResponse1[0];
var b = a.CustomerData;
To extract the first element (Key) try this method and it will be the same for the others :
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync("Your URL"))
{
var apiResponse = await response.Content.ReadAsStringAsync();
var list = JObject.Parse(apiResponse)["Attributes"].Select(el => new { Key= (string)el["Key"] }).ToList();
var Keys= list.Select(p => p.Key).ToList();
}
}
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
worked!

Getting error deserialising JSON to List<T>

I want to deserialize this json to a List of Product objects but i get this error:
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ShoppingList.Product]' 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.
This is my code:
{
"records": [
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
}
public class Product
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public decimal price { get; set; }
public int category_id { get; set; }
public string category_name { get; set; }
}
public async Task<List<Product>> GetProductsAsync()
{
Products = new List<Product>();
var uri = new Uri("https://hostname/api/product/read.php");
try
{
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
Products = JsonConvert.DeserializeObject<List<Product>>(content);
}
}
catch (Exception )
{
throw;
}
return Products;
}
Your Json is not a List<Product>, its an object with a single property called records which is a List<Product>.
So your actual C# model is this:
public class RootObject
{
public List<Product> records { get; set; }
}
And you deserialize like this:
RootObject productsRoot = JsonConvert.DeserializeObject<RootObject>(content);
The issue is that your response JSON you've provided is an object which contains a list, but you are trying to deserialize the data into a straight list. I think all you need to do is add a second class which contains the list into your code, then deserialize using that list.
public class Product
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public decimal price { get; set; }
public int category_id { get; set; }
public string category_name { get; set; }
}
public class RootProduct
{
public List<Product> Products {get;set;}
}
Then you change your deserialization portion from List to
RootProduct response = JsonConvert.DeserializeObject<RootProduct>(content);
The usage would then simply be products. response.Products to access the list of items.
The problem is your json structure. Below is an example of a json array - notice i removed the property "records".
[
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
Given this data
[
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
And this class definition
public class Order
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public string price { get; set; }
public string category_id { get; set; }
public string category_name { get; set; }
}
The code to convert it from JSON to a C# List<Order> is:
public static List<Order> Map(string json)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(json);
}

Cannot deserialize the JSON array (e.g. [1,2,3]) into type ' ' because type requires JSON object (e.g. {"name":"value"}) to deserialize correctly

I have this JSON:
[
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 1",
"Values": [
"Acc 1"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "1",
"Values": [
"1"
]
}
}
],
"Name": "account",
"Id": "1"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 2",
"Values": [
"Acc 2"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "2",
"Values": [
"2"
]
}
}
],
"Name": "account",
"Id": "2"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 3",
"Values": [
"Acc 3"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "3",
"Values": [
"3"
]
}
}
],
"Name": "account",
"Id": "2"
}
]
And I have these classes:
public class RetrieveMultipleResponse
{
public List<Attribute> Attributes { get; set; }
public string Name { get; set; }
public string Id { get; set; }
}
public class Value
{
[JsonProperty("Value")]
public string value { get; set; }
public List<string> Values { get; set; }
}
public class Attribute
{
public string Key { get; set; }
public Value Value { get; set; }
}
I am trying to deserialize the above JSON using the code below:
var objResponse1 = JsonConvert.DeserializeObject<RetrieveMultipleResponse>(JsonStr);
but I am getting this error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'test.Model.RetrieveMultipleResponse' 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. Path
'', line 1, position 1.
Your json string is wrapped within square brackets ([]), hence it is interpreted as array instead of single RetrieveMultipleResponse object. Therefore, you need to deserialize it to type collection of RetrieveMultipleResponse, for example :
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
If one wants to support Generics (in an extension method) this is the pattern...
public static List<T> Deserialize<T>(this string SerializedJSONString)
{
var stuff = JsonConvert.DeserializeObject<List<T>>(SerializedJSONString);
return stuff;
}
It is used like this:
var rc = new MyHttpClient(URL);
//This response is the JSON Array (see posts above)
var response = rc.SendRequest();
var data = response.Deserialize<MyClassType>();
MyClassType looks like this (must match name value pairs of JSON array)
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class MyClassType
{
[JsonProperty(PropertyName = "Id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "Description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "Manager")]
public string Manager { get; set; }
[JsonProperty(PropertyName = "LastUpdate")]
public DateTime LastUpdate { get; set; }
}
Use NUGET to download Newtonsoft.Json add a reference where needed...
using Newtonsoft.Json;
Can't add a comment to the solution but that didn't work for me. The solution that worked for me was to use:
var des = (MyClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(MyClass));
return des.data.Count.ToString();
Deserializing JSON array into strongly typed .NET object
Use this, FrontData is JSON string:
var objResponse1 = JsonConvert.DeserializeObject<List<DataTransfer>>(FrontData);
and extract list:
var a = objResponse1[0];
var b = a.CustomerData;
To extract the first element (Key) try this method and it will be the same for the others :
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync("Your URL"))
{
var apiResponse = await response.Content.ReadAsStringAsync();
var list = JObject.Parse(apiResponse)["Attributes"].Select(el => new { Key= (string)el["Key"] }).ToList();
var Keys= list.Select(p => p.Key).ToList();
}
}
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
worked!

Categories