Reputation: 805
New to C# and Visual Studio so bear with me and suggestions to do something better are very open.
I want to make a program to display and edit JSON using a DataGridView. The application will download some JSON from the web (got that part) and then display it for simple editing in the application and when it is finished being edited it is uploaded back to the server. The problem is I'm getting stuck on the part where the JSON displays (probably an important part).
I've found out that I should be using a DataGridView to display it (at least that is the impression I've gotten from some searching around) and I am able to successfully download and deserialize the JSON (using JSON.NET) using some simple Lists and Dictionaries. I'd like to be able to deserialize the JSON into classes so I am able to more easily navigate it but it has proven quite difficult using my nested dictionaries and arrays. Here is a sample (the real file is a bit longer but I've cut it out so you get the gist).
{
"regular" : [
[
{
"description" : "Free E-Booklet",
"information" : "http://freeebooknotascam.com",
"contentType" : "banner",
"message" : "Free E-Booklet (NOT A SCAM!)",
"color" : "#811cca"
}
],
[
{
"description" : "Free Money!",
"information" : "http://freemoney.com",
"title" : "",
"contentType" : "web",
"thumbnail" : "http://freemoney.com/money"
}
]
],
"special" : [
{
"description" : "Hats",
"information" : "",
"title" : "",
"contentType" : "web",
"thumbnail" : "http://hats.com/mlady"
},
{
"description" : "Signup",
"information" : "",
"title" : "",
"contentType" : "web",
"thumbnail" : "http://google.com/signup/thumbnail.png"
}
]
}
I've tried simple classes with just nested lists and dictionaries as they appear but JSON.NET doesn't want to deserialize it and display it into the DataGridView.
This is what I am currently using to deserialize and it works but it doesn't display in the DataGridView (only displays counts and I can't traverse up and down it). JsonConvert.DeserializeObject<Result>(json);
where result is just this.
public class Result
{
public List<Dictionary<String, String>> featured;
public List<List<Dictionary<String, String>>> regular;
}
In one view I'd like to list the description
tag of the item fro the regular
dictionaries e.g.
- Regular
- Row One
- Free E-Booklet
- Row Two
- Free Money
and in the other would list the special
dictionaries
- Special
- Hats
- Signup
Upvotes: 1
Views: 2502
Reputation: 14241
I used the JavaScriptSerializer, but it does not matter.
Since the keys in the dictionaries are different and unknown in advance (as I suggested), then use DataTable
. It allows you to create columns dynamically.
var text = File.ReadAllText("file.txt");
var jss = new JavaScriptSerializer();
var root = (Dictionary<string, object>)jss.DeserializeObject(text);
var data = root.SelectMany(pair => ((object[])pair.Value));
var dt = new DataTable();
dt.Columns.Add("special", typeof(bool)).ReadOnly = true;
// regular
foreach (var arr in data.OfType<object[]>())
foreach (Dictionary<string, object> dict in arr)
foreach (var key in dict.Keys)
if (!dt.Columns.Contains(key))
dt.Columns.Add(key);
foreach (var arr in data.OfType<object[]>())
foreach (Dictionary<string, object> dict in arr)
{
var row = dt.NewRow();
foreach (var pair in dict)
row[dt.Columns[pair.Key]] = pair.Value;
dt.Rows.Add(row);
}
// special
foreach (var dict in data.OfType<Dictionary<string, object>>())
foreach (var key in dict.Keys)
if (!dt.Columns.Contains(key))
dt.Columns.Add(key);
foreach (var dict in data.OfType<Dictionary<string, object>>())
{
var row = dt.NewRow();
row["special"] = true;
foreach (var pair in dict)
row[dt.Columns[pair.Key]] = pair.Value;
dt.Rows.Add(row);
}
dataGridView.DataSource = dt;
To indicate which set - regular or special - a row belongs, I added a boolean column. Instead, you can use two different DataGridView
.
Result:
Upvotes: 2