Below I have a JSON that details an array of objects, each of which have a values property.
This values property is also an object, but each values object may contain any number of strings:
{
"data": [
{
"name": "xxxx",
"values": {
"one": "xxxx",
"two": false
}
},
{
"name": "xxyy",
"values": {
"three": "xxyy",
"four": 1.25,
"five": "xxyy"
}
},
{
"name": "xxyy",
"values": {
"six": "xxyy",
"seven": "xxyyy",
"eight": "xxyy",
"nine": 1234,
"ten": 0
}
}
]
}
Is there a way I can go about deserializing this JSON object so that I'm able to populate a values object, regardless of the number of properties this values object has?
I'm using C# and Newtonsoft.Json to deserialize this.
The below two objects can be used to deserialize the JSON properly:
public class AllData
{
public Item[] Data { get; set; }
}
public class Item
{
public string Name { get; set; }
public IDictionary<string, object> Values { get; set; }
}
And then the following lines can be used to actually do the deserialization:
string json = /*json*/;
AllData data = JsonConvert.DeserializeObject<AllData>(json);
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'm currently working on a webservice, and I have this behavior that I haven't encountered until today. Here's the class I'm returning:
public class Block
{
public int order { get; set; }
public string title { get; set; }
public Dictionary<string, object> attributes { get; set; }
}
attributes can contain any kind of value: simple type, object, array, etc.
And when I return a Block object through my webservice, here's what I get:
{
"order": 1,
"attributes": [
{
"Key": "key1",
"Value": "value1"
},
{
"Key": "key2",
"Value": "value2"
}
],
"title": "Title"
}
Does anyone know why I'm not simply getting a "key1": "value1" output?
First of all your JSON is not valid, please be aware there are no , after "order": 1 this line.
After this correction you can change your class structure like this
public class Attribute
{
public string Key { get; set; }
public object Value { get; set; }
}
public class Block
{
public int order { get; set; }
public List<Attribute> attributes { get; set; }
public string title { get; set; }
}
this way you will be able to deserialize your JSON, I used simply this website https://json2csharp.com/ for converting your JSON into C# class
As for usage you can do .FirstOrDefault(x=>x.Key=="key1") to get whichever data you want, or if you will process all the list one by one you can simply do attributes.Count
When I do
var x = new Class
{
order = 1,
title = "Title",
attributes = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", "value2" }
}
};
var json = JsonConvert.SerializeObject(x);
Console.WriteLine(json);
I get
{"order":1,"title":"Title","attributes":{"key1":"value1","key2":"value2"}}
Do you have code that serializes your data or does ASP.NET do it for you?
I have a json array as ahown below with two keys "entities" and "TotalResults". within entities there is "Fields". I want to obtain the elements within "Fields" i.e, "name" and "values". so that i can iterate over the Fields to find the matching name and it's respective value. I have tried most of the solutions out there, nothing seems to give the result i want. Any help would be admired.
below is the Json array :
{"entities": [
{
"Fields": [
{
"Name": "test-id",
"values": [
{
"value": "268"
}
]
},
{
"Name": "os-config",
"values": [
{}
]
},
{
"Name": "pc-mobile-host",
"values": [
{}
]
}
}
],
"TotalResults": 2}
Code i tried are below (only two are mentioned though i tried lots of other methods) :
1.
Dictionary<string,object> Result= JsonConvert.DeserializeObject<Dictionary<string,object>>(json);
2.
public class Fields
{
[JsonProperty("values")]
public IList<object> values { get; set; }
[JsonProperty("Name")]
public string Name { get; set; }
}
public class RootObject
{
public IList<Fields> Fields { get; set; }
}
var Result = JsonConvert.DeserializeObject<RootObject>(json);
First (using Newtonsoft.Json) parse json to JObject and then you can access and iterate Fields objects using SelectToken.
There was still error in your JSON while writing this answer so I've modified it to be valid
var json = #"{""entities"":[{""Fields"":[{""Name"":""test-id"",""values"":[{""value"":""268""}]},{""Name"":""os-config"",""values"":[{}]},{""Name"":""pc-mobile-host"",""values"":[{}]}]}],""TotalResults"":2}";
var jObject = JObject.Parse(json);
var fields = jObject.SelectToken("$..Fields").ToList();
foreach (var field in fields)
{
}
Maybe someone knows better version to resolve my problem?
Have next json:
[
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
},
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
},
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
}
]
I want parse elements from json to my classes:
public class Name
{
public bool IsEmpty { get; set; }
public double X { get; set; }
public double Y { get; set; }
}
public class RootObject
{
public List<Name> name { get; set; }
public string password { get; set; }
}
......
dynamic res = JsonConvert.DeserializeObject<RootObject[]>(result1);
Variable result1 is my json object.
And exeption, what I have:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'client_app.MainPage+RootObject[]' 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 'name', line 1, position 8.
The problem resides in the mapping between your JSon string and your root object. I think that this is what causes the problem:
"IsEmpty":false
When deserializing your object the JSon converter waits for the IsEmpty property to be of type bool.
Which is not the case since its type is List
So your root class should be like this:
public class RootObject
{
public Name name { get; set; }
public string password { get; set; }
}
Please try like this:
var res = JsonConvert.DeserializeObject<List<RootObject>>(result1);
This is the set of classes you need to deserialize
public class Name
{
public bool IsEmpty { get; set; }
public double X { get; set; }
public double Y { get; set; }
}
public class Item
{
public Name name { get; set; }
public string password { get; set; }
}
then
var items = Newtonsoft.Json.JsonConvert.DeserializeObject<Item[]>(json);
var ds = new DataContractJsonSerializer(typeof(RootObject[]));
var msnew = new MemoryStream(Encoding.UTF8.GetBytes(MyJsonString));
RootObject[] items = (RootObject[])ds.ReadObject(msnew);
This resolve my problem
Your Name class has the property of IsEmpty as a List of bools.
So you Json should be:
[
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
},
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
},
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
}
]
Note the sqaure brackets on the value of IsEmpty, which signifies the value is in a collection. if you want to assign more than one value then you can add more using:
"IsEmpty": [ false, true ]
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!