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
},
]
}
*/
Related
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!
I have following json:
{
"Australia": {
"count": 2,
"records": {
"File1.ppt": {
"id": "123456789"
},
"File2.doc": {
"id": "987654321"
}
}
},
"PDFs.zip": {
"count": 0,
"records": {}
},
"Peru": {
"count": 2,
"records": {
"File3.PPT": {
"id": "897456123"
},
"File4.PPT": {
"id": "123546789"
}
}
},
"total count": 4
}
and to deserialize the above json I have defined some classes so that I can use these classes while deserializing my json into objects and below are the classes:
namespace GEO_Batch_Creation
{
[DataContract]
class BhpIdJson
{
[DataMember(Name = "objects")]
public Dictionary<string, Country[]> Countries { get; set; }
[DataMember(Name = "total count")]
public int TotalCount { get; set; }
}
[DataContract]
class Country
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "records")]
public Dictionary<string, Record> Records { get; set; }
}
[DataContract]
class Record
{
[DataMember(Name = "filename")]
public string FileName { get; set; }
[DataMember(Name = "id")]
public Dictionary<string, string> BhpId { get; set; }
}
}
But when I use following code to deserialize the json I am getting only total count.
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BhpIdJson));
BhpIdJson bsObj2 = (BhpIdJson)deserializer.ReadObject(ms);
}
Please suggest me where I am doing mistake.
I don't think that this JSON is in correct format. I don't know if you got this from somewhere or made for yourself, but if the last one I recommend you to change the structure.
Even in C# you cant realy create a class that has the objects and the count of the object in the same List or Array etc.
Based on your class your JSON yhould look like this:
{
"objects": [
{
"name": "Australia",
"count": 2,
"records": [
{
"fileName": "File1.ppt",
"id": "123456789"
},
{
"fileName": "File2.doc",
"id": "987654321"
}
]
}
],
"total count": 4
}
As you can see you have to add Name or something to your Country class. I hope it helped.
Edit:
You can create a list like I mentioned above but it's not a good practice I think.
I'm using Json.NET to deserialize incoming json data into an object, but I want to flatten one of the a nested data into a property as an array.
What my incoming json data looks like:
{
“sets": {
"set": [
{
"name": "Act 1:",
“title”: [
{
"name": “A”
},
{
"name": “B”
},
{
"name": “C”
},
{
"name": “D”
}
]
},
{
"name": "Act 2:",
“title”: [
{
"name": “E”
},
{
"name": “F”
},
{
"name": “G”
}
]
}
]
}
}
What I want the transformed data to look like when object is serialized:
{
“sets": {
“title”: [
{
"name": “A”
},
{
"name": “B”
},
{
"name": “C”
},
{
"name": “D”
},
{
"name": “E”
},
{
"name": “F”
},
{
"name": “G”
}
]
}
}
What approach can I take to achieve this? Is it possible to customize how my object gets deserialized?
I know you are asking for it to be done in the deserialization but this gives the same results.
https://dotnetfiddle.net/U89KwW
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public const string Json = "{\"sets\": {\"set\": [{\"name\": \"Act 1:\",\"title\": [{\"name\":\"A\"},{\"name\": \"B\"},{\"name\": \"C\"},{\"name\": \"D\"}]},{\"name\": \"Act 2:\",\"title\": [{\"name\": \"E\"},{\"name\": \"F\"},{\"name\": \"G\"}]}]}}";
public static void Main()
{
Something something = JsonConvert.DeserializeObject<Something>(Json);
something.Titles = something.sets.set.SelectMany(c=> c.title).ToList();
something.sets = null;
string JsonResult = JsonConvert.SerializeObject(something);
Console.WriteLine(JsonResult);
}
}
public class Something
{
public Sets sets {get;set;}
public List<Title> Titles {get;set;}
}
public class Sets
{
public List<Set> set {get;set;}
}
public class Set
{
public string name {get;set;}
public List<Title> title {get;set;}
}
public class Title
{
public string name {get;set;}
}
[
{
"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; }
}
First: I'm new to using JSON, and I used the answers on here to use Json.Net to deserialize data from a Pokemon API into a C# class (Pokemon class). I used http://json2csharp.com to help me define my class and it looks like this:
public class Pokemon
{
public Pokemon(string json)
{
JsonConvert.PopulateObject(json, this, PokeApi.JsonSerializerSettings);
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("evolutions")]
public Evolutions evolutions { get; set; }
[JsonProperty("national_id")]
public int national_id { get; set; }
}
with a bunch of other properties like resource_uri, attack stat, etc.
As the answer offered on the aforementioned link said, I used JsonConvert.DeserializeObject(json) like so:
public Pokemon GetPokemon(int nationalId)
{
using (WebClient client = new WebClient())
{
var json = client.DownloadString("http://pokeapi.co/api/v1/pokemon/" + nationalId + "/");
var output = JsonConvert.DeserializeObject<Pokemon>(json);
return output;
}
}
However I keep getting an exception that says "Cannot deserialize the current JSON array (e.g.[1,2,3]) into type 'Evolutions' because the type requires a JSON object..."
I found a lot of other questions asking the same exact thing, but I was confused with the top answers - sometimes the answer was to use JsonProperty, sometimes it was to use JsonConverter, without really an explanation on what all these meant. Do I need both?
Edit: sample json (call: http://pokeapi.co/api/v1/pokemon/1/)
{
"abilities": [
{
"name": "overgrow",
"resource_uri": "/api/v1/ability/1/"
},
{
"name": "chlorophyll",
"resource_uri": "/api/v1/ability/2/"
}
],
"attack": 49,
"catch_rate": 45,
"created": "2013-11-02T12:08:25.745455",
"defense": 49,
"egg_cycles": 21,
"egg_groups": [
{
"name": "Monster",
"resource_uri": "/api/v1/egg/1/"
},
{
"name": "Grass",
"resource_uri": "/api/v1/egg/8/"
}
],
"ev_yield": "1 Sp Atk",
"evolutions": {
"level": 16,
"method": "level up",
"resource_uri": "/api/v1/pokemon/2/",
"to": "Ivysaur"
},
"exp": 64,
"growth_rate": "ms",
"happiness": 70,
"height": "2'4",
"hp": 45,
"male_female_ratio": "87.5/12.5",
"modified": "2013-11-02T13:28:04.914889",
"moves": [
{
"learn_type": "other",
"name": "Tackle",
"resource_uri": "/api/v1/move/1/"
},
{
"learn_type": "other",
"name": "Growl",
"resource_uri": "/api/v1/move/2/"
},
{
"learn_type": "level up",
"level": 10,
"name": "Vine whip",
"resource_uri": "/api/v1/move/3/"
}
],
"name": "Bulbasaur",
"national_id": 1,
"resource_uri": "/api/v1/pokemon/4/",
"sp_atk": 65,
"sp_def": 65,
"species": "seed pokemon",
"speed": 45,
"total": 318,
"types": [
{
"name": "grass",
"resource_uri": "/api/v1/type/5/"
},
{
"name": "poison",
"resource_uri": "/api/v1/type/8/"
}
],
"weight": "15.2lbs"
}
Evolutions class:
public class Evolutions
{
public int level { get; set; }
public string method { get; set; }
public string resource_uri { get; set; }
public string to { get; set; }
}
I tried http://json2csharp.com/ with http://pokeapi.co/api/v1/pokemon/19/ and what I see is
public class RootObject
{
//...
public List<Evolution> evolutions { get; set; }
//...
}
This pretty mush is your Pokemon class. So you need to declare Evolutions as list.