This question already has answers here:
How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?
(22 answers)
Closed 2 years ago.
I have a scnerio where i donot know the names of the keys so properties can;t be created beforehand.
The JSON needs to be parsed and loaded into Dictionary that is present in a class.
The format of JSON is like
"SearchCriteria":{
"firstname":"user1",
"surname":"User2"
},
"RequiredGroups":{
"UserGroup":"g1",
"TeacherGroup":"g2"
}
The problem is that the Parameters count and name are not known and can be anything.
The JSON also contains other sections as well such as RequiredGroups which have known key names and are mapped with Objects.
Need to convert into Dictionary. Any leads....
Example using Newtonsoft.Json.Linq:
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"{'SearchCriteria':{'firstname':'user1','surname':'User2'},'RequiredGroups':{'UserGroup':'g1','TeacherGroup':'g2'}}";
JObject o = JObject.Parse(json);
var dict = o.ToObject<Dictionary<string, object>>();
}
}
string str1 = "{\"SearchCriteria\":{ \"firstname\":\"user1\", \"surname\":\"User2\" }, \"RequiredGroups\":{ \"UserGroup\":\"g1\",\"TeacherGroup\":\"g2\" }}";
var jObject1 = JObject.Parse(str1);
Dictionary<string, string> dictObj = new Dictionary<string, string>();
IList<string> keys = jObject1.Properties().Select(p => p.Name).ToList();
foreach(var k in keys)
{
var s = jObject1[k].ToString();
dictObj.Add(k, s);
}
Related
I'm quite new to JSON, and am currently learning about (de)serialization.
I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :
{
"daily": {
"1337990400000": 443447,
"1338076800000": 444693,
"1338163200000": 452282,
"1338249600000": 462189,
"1338336000000": 466626
}
}
For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:
dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");
You can then do:
var str = obj.x;
However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:
var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];
Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:
Dictionary<string, Dictionary<string, int>>
I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).
Newtonsoft.Json
Use DeserializeObject<T> from JsonConvert:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
System.Text.Json
Use Deserialize<T> from JsonSerializer:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);
This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.
Or try this:
string json = "
{ daily:[
{ key: '1337990400000', val:443447 },
{ key: '1338076800000', val:444693 },
{ key: '1338163200000', val:452282 },
{ key: '1338249600000', val:462189 },
{ key: '1338336000000', val:466626 }]
}";
public class itemClass
{
public string key; // or int
public int val;
}
public class items
{
public itemClass[] daily;
}
items daily = (new JavascriptSerializer()).Deserialize<items>(json);
Then you can:
var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();
This question already has answers here:
How can I deserialize JSON with C#?
(19 answers)
Closed 2 years ago.
I have method where I call another API. From
var activeCustomers = await response.Content.ReadAsStringAsync();
I get string which contains [timestamp, value] objects:
{"values":[[1298937600000,1],[1459468800000,16],[1462060800000,527],[1464739200000,173],[1467331200000,132],[1470009600000,166],[1472688000000,151],[1475280000000,172],[1477958400000,139],[1480550400000,129],[1483228800000,116],[1485907200000,133],[1488326400000,180],[1491004800000,227],[1493596800000,281],[1496275200000,263],[1498867200000,230],[1501545600000,326],[1504224000000,403],[1506816000000,442],[1509494400000,1019],[1512086400000,650],[1514764800000,708],[1564617600000,2614],[1567296000000,2527],[1569888000000,3144],[1572566400000,3075],[1575158400000,2541],[1577836800000,2246],[1580515200000,2456],[1583020800000,885]]}
I want to parse these values into key value pairs, but I am not sure what's the most optimal way for that.
I tried removing beginning and ending of string and cast it as object but it stays as one big string inside the ienumerable:
int index = activeCustomers.IndexOf(":");
if (index > 0)
activeCustomers = activeCustomers.Substring(index + 1);
activeCustomers = activeCustomers.Remove(activeCustomers.Length - 1);
var results = ((IEnumerable) activeCustomers).Cast<object>();
I also tried making regex for that but I am not very comfortable with that.
This just a JSON with array of arrays, which can be easily deserialized using Json.NET
var result = JsonConvert.DeserializeObject<Root>(activeCustomers);
or System.Text.Json
var result = JsonSerializer.Deserialize<Root>(activeCustomers);
Where Root is
public class Root
{
public long[][] values { get; set; }
}
Then you can map the values property to any desired structure using Select method
var pairs = result.values.Select(v => new { timestamp = v[0], value = v[1] }).ToList();
I have a big problem with deserializing my JSON to an object. It should be deserialized to IList<KeyValuePair<string, object>> the problem is that the keys have white spaces.
"spec": {
"SOMETHING WITH SPACES" : "10"
etc.
...
}
public class SomeObject
{
...
public IList<KeyValuePair<string, object>> spec{ get; set; }
...
}
Deserializing code:
var sr = new ServiceStack.Text.JsonSerializer<SomeObject>();
var esResult = sr.DeserializeFromString(responseJson);
responseJson is a GET from ElasticSearch.
What I get to my field it is null.
If I have key without whitespaces it's deserializing normally and I'm getting my IList<KeyValuePair<string, object>>
You can't use IList or List here, because your source JSON has no [ ] in it, which is a requirement if you want to parse into such a collection. In other words, without [ ] you can't parse into a collection, at least not without going through lots of hoops.
Instead you need to use a Dictionary as was suggested already in comments.
Note: I used Newtonsoft JsonConvert because you didn't state what your parser is, but that should make little or no difference to my arguments.
Working code:
var json = "{ \"spec\": { \"SOMETHING WITH SPACES\" : \"10\" } }";
var someObj = JsonConvert.DeserializeObject<SomeObject>(json);
public class SomeObject
{
public Dictionary<string, object> spec{ get; set; }
}
After that, you can cast the spec property to an IEnumerable and loop through whatever was found:
foreach (var pair in someObj.spec as IEnumerable<KeyValuePair<string, object>>)
{
Console.WriteLine(pair.Key + " -> " + pair.Value);
}
Or even convert it to a List:
var list = someObj.spec.ToList();
foreach (var pair in list)
{
Console.WriteLine(pair.Key + " -> " + pair.Value);
}
.NET Fiddle: https://dotnetfiddle.net/15l2R3
If you don't mind using Newtonsoft.Json:
const string json = #"{""spec"": { ""SOMETHING WITH SPACES"" : ""10"", ""SOMETHING WITH MORE SPACES"" : ""20"" }}";
dynamic data = JsonConvert.DeserializeObject(json);
Dictionary<string, string> list = data["spec"].ToObject<Dictionary<string, string>>();
foreach (var item in list)
{
Console.WriteLine(item.Key + ", " + item.Value);
}
I guess your JSON serialiazer makes some trouble. I'd recommend to use Newtonsoft.Json (in NuGet)
I've tried following code, and it works fine:
var o1 = new SomeObject() { spec = new List<KeyValuePair<string, object>>() };
o1.spec.Add(new KeyValuePair<string, object>("test with spaces", 10));
var r1 = Newtonsoft.Json.JsonConvert.SerializeObject(o1);
Console.WriteLine(r1);
var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject<SomeObject>(r1);
var r2 = Newtonsoft.Json.JsonConvert.SerializeObject(o2);
Console.WriteLine(r2);
The outcome is
{"spec":[{"Key":"test with spaces","Value":10}]}
{"spec":[{"Key":"test with spaces","Value":10}]}
No null values, all works fine.
EDIT: I actually see no reason, why spaces should be any problem at all. They are just part of the string.
This question already has answers here:
Multi-key dictionary in c#? [duplicate]
(16 answers)
Closed 4 years ago.
hi how could I make array like this in c#??:
settings width and height is loaded from file
properties["settings"]["width"] = "bbb";
properties["settings"]["height"] = "cccc";
and dynamic_string_key is keys loaded from file and I dont know how many or what key name and values will be :)
properties["sets_of_data"][dynamic_string_key]= "lalala";
properties["sets_of_data"][dynamic_string_key]= "lalala";
properties["sets_of_data"][dynamic_string_key]= "lalala";
properties["sets_of_data"][dynamic_string_key]= "lalala";
Arrays in C# only allow you to find an element by the index (integer), not by an arbitrary string. In C#, that's a Dictionary<>.
You can use a dictionary of a dictionary, but it's not as easy:
var data = new Dictionary<string, Dictionary<string, string>>();
data["settings"] = new Dictionary<string, string>();
data["settings"]["width"] = "bbb";
But that seems overly complicated. If you know you'll have "settings", then it's probably more readable to just have one dictionary for settings:
var settings = new Dictionary<string, string>();
settings["width"] = "bbb";
If your file is JSON you can use JSON.NET and do it like this
JObject obj = JObject.Parse(File.ReadAllText("foo.json"));
var bar = (string)obj["foo"]["bar"];
you can use
Dictionary<string, Dictionary<string, string>> properties =
Dictionary<string, Dictionary<string, string>>
{
{
"settings",
new Dictionary<string, string>
{
{"width", "200"},
{"height", "150"},
}
}
};
Or you can use Tuples, especially named tuples
var exampleNamedTuple = (Height: 0, Width: 0, Value: "");
var list = new List<(int Height, int Width, string Value)>();
list.Add(exampleNamedTuple);
var height = list.First().Height;
var width = list.First().Width;
var value = list.First().Value;
then you can assign it to your settings property.
https://learn.microsoft.com/en-us/dotnet/csharp/tuples
I'm quite new to JSON, and am currently learning about (de)serialization.
I'm retrieving a JSON string from a webpage and trying to deserialize it into an object. Problem is, the root json key is static, but the underlying keys are dynamic and I cannot anticipate them to deserialize. Here is a mini example of the string :
{
"daily": {
"1337990400000": 443447,
"1338076800000": 444693,
"1338163200000": 452282,
"1338249600000": 462189,
"1338336000000": 466626
}
}
For another JSON string in my application, I was using a JavascriptSerializer and anticipating the keys using class structure. What's the best way to go about deserializing this string into an object?
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
You can use dynamic in .NET 4 or later. For example with JSON.NET I can do:
dynamic obj = JsonConvert.Deserialize<dynamic>("{x: 'hello'}");
You can then do:
var str = obj.x;
However, unsure how it will handle numeric keys. You can of course just use JObject directly itself, for example:
var obj = JObject.Parse("{'123456': 'help'}");
var str = obj["123456"];
Whenever you have JSON with dynamic keys it can usually be deserialized into a Dictionary<string, SomeObject>. Since the inner JSON keys are dynamic (in this question) the JSON can be modelled as:
Dictionary<string, Dictionary<string, int>>
I would recommend using NewtonSoft.Json (JSON.Net) or System.Text.Json (if you're working in .NET-Core 3.0 and up).
Newtonsoft.Json
Use DeserializeObject<T> from JsonConvert:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);
System.Text.Json
Use Deserialize<T> from JsonSerializer:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);
This is not convenient to use, because in с# can not be defined a variable starts with a number. Add prefix to keys.
Or try this:
string json = "
{ daily:[
{ key: '1337990400000', val:443447 },
{ key: '1338076800000', val:444693 },
{ key: '1338163200000', val:452282 },
{ key: '1338249600000', val:462189 },
{ key: '1338336000000', val:466626 }]
}";
public class itemClass
{
public string key; // or int
public int val;
}
public class items
{
public itemClass[] daily;
}
items daily = (new JavascriptSerializer()).Deserialize<items>(json);
Then you can:
var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();