Parsing JSON with fastJson in C# - c#

I could not find an answer in the existing threads for my problem. I have this JSON string:
{
"Count": 4,
"Result:000": {
"Score": 4.571,
"W0DateTime": "2014-08-28 23:00:00",
"W0Value": 1.0164,
"W0Fibonacci": 0,
"Direction": "SHORT",
"StartDate": "2014-08-29 16:30:00",
"EndDate": "2014-08-28 01:00:00",
"BarsCalculated": 80
}
}
How do I get the content of Result:000?
I have this code:
...
public Dictionary<string, object> dictionaryObject;
public void jsonInitStructure(string sJsonString)
{
dictionaryObject = (Dictionary<string , object>) fastJSON.JSON.Parse(sJsonString);
}
...
Count is easy: Convert.ToInt32(dictionaryObject ["Count"]) but how do I get the values from Result:000? For example (Score, StartDate, EndDate, ...)

Have you tried casting it?
var result000 = (Dictionary<string, object>)dictionaryObject["Result:000"];
var result000Score = Convert.ToDouble(result000["Score"]);

Plese have a try...
Array objList = (Array)dictionaryObject["Result:000"] ;
foreach (object obj in objList)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary = (Dictionary<string, object>)obj;
var var1 = dictionary["Score"].ToString();
var var2 = dictionary["W0DateTime"].ToString();
}

Related

Making Hierarchical dictionary in c#

I want to build a hierarchical dictionary structure in C# from an Excel data sheet. The structure should look like this:
{
"Data": {
survey_id: {
"SurveyParameter": {},
"SurveySetting": {},
"Boreholes": {
borehole_id: {
"BoreholeParameter": {},
"BoreholeSetting": {},
"Layers": {
"Geology": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
"Contamination": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
},
}
},
}
}
}
"""
An example image of Excel data sheet from which the dictionary structure is to be built is provided here:
image of excel_data
I have built a dictionary structure that looks like this second image (below). But I want to convert it to the hierarchical structure, shown at the top.
image of the built dictionary
here is the text format of the dictionary saved as json file:
"3": {
"(SurveyParameter, SurveyId)": "[Company-Year]",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "[UTM, Revit]",
"(BoreholeParameter, BoreholeId)": null,
"(BoreholeSetting, AllowOverwrite)": "[True / False (default)]",
"(BoreholeSetting, Easting)": "[m] (X-Coordinate)",
"(BoreholeSetting, Northing)": "[m] (Y-Coordinate)",
"(BoreholeSetting, Elevation)": "[m] (Z-Coordinate)",
"(BoreholeParameter, BoreholeDiameter)": "[m] (default 0.4 m)",
"(Parameter, LayerId)": null,
"(Parameter, InputLayerStartDepth)": "(automatically filled)",
"(Parameter, InputLayerEndDepth)": "[m] (relative to coordinate)",
"(LayerSetting, SoilType)": "(pre-defined)",
"(Parameter, HomogeneousAreaSoil)": "(pre-defined)",
"(Parameter, SoilDescription)": null
},
"4": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_1",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 1.7,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"5": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_2",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.2,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"6": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_3",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.3,
"(LayerSetting, SoilType)": "Bohrhindernis",
"(Parameter, HomogeneousAreaSoil)": "Bohrhindernis",
"(Parameter, SoilDescription)": "Bohrhindernis"
I used the following code to build the dictionary in second image:
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
Dictionary<string,Dictionary<(object, object), object>> rows = new Dictionary<string,Dictionary<(object, object), object>> ();
foreach (DataTable table in tables)
{
//DataRow selectedRow = table.Rows[3];
//DataRow newRow = table.NewRow();
//newRow.ItemArray = selectedRow.ItemArray; // copy data
//table.Rows.Remove(selectedRow);
//table.Rows.InsertAt(newRow, 3 + 1 / -1);
//table.Rows.Remove(table.Rows[0]);
Dictionary<(object, object), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(object, object), object>();
foreach (DataColumn col in table.Columns)
{
object FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
object SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
//string 3rdcolname = table.Rows[3][col.ColumnName].ToString(); //index the 2nd row with the column name
// Tuple<string,string> column_name_keys = new Tuple<string,string>(FirstcolName.ToString(), SecondcolName.ToString());
//col.ColumnName = column_name_keys;
// table.Rows[0].Delete();
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
}
string json = JsonConvert.SerializeObject(rows, Formatting.Indented);
File.WriteAllText(#"D:\Data\test.json", json);
}
}
}
Posting the developed code for people who might need it or might be stuck in a similar problem.
This code below works for the most part as it makes the dictionary structure. However it needs to be improved with introduction of Flexible nested dictionaries that can take any types of values(including Dictionaries). This one generates the Survey_level Dictionary atleast: The nested borehole dictionary structure can only be added when we have a class that combines Boreholes Dictionary, SurveyParameter Dictionary & SurveySetting Dictionary
...
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
//If you declared nested dict as object you couldn't do any operations with it that are provided by Dictionary, only the ones valid for all objects.
Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>> dict_coll = new Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>>();
Dictionary<string, Dictionary<(string, string), object>> rows = new Dictionary<string, Dictionary<(string, string), object>>();
Dictionary<(string, string), object> row_usable = new Dictionary<(string, string), object>();
foreach (DataTable table in tables)
{
Dictionary<(string, string), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(string, string), object>();
foreach (DataColumn col in table.Columns)
{
string FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
string SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
rows.Remove("0");
rows.Remove("1");
rows.Remove("3");
List<(string, string)> row_Keys = new List<(string, string)>(row.Keys);
List<object> row_vals = new List<object>(row.Values);
row_usable = row_Keys.Zip(row_vals, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
}
dict_coll.Add(table.TableName.ToString(), rows);
}
var guid_data = rows.ElementAt(0).Value; //or use trygetvalue()
var SURVEY_ID = ("SurveyParameter", "SurveyId");
var BOREHOLE_ID = ("BoreholeParameter", "BoreholeId");
var LAYER_ID = ("Parameter", "LayerId");
Dictionary<string, object> guid_dict = new Dictionary<string, object>();
Dictionary<string, Dictionary<string,Dictionary<string,object>>> data_dict =
new Dictionary<string, Dictionary<string, Dictionary<string, object>>>();
//Dictionary<string,object?> data_dict =
// new Dictionary<string,object?>();
//Hashtable data_dict = new Hashtable;
Hashtable restructured = new Hashtable();
restructured.Add("ParameterGuid", guid_dict);
restructured.Add("Data", data_dict);
List<string> guid_dict_keys = guid_dict.Keys.OfType<string>().ToList();
List<string> data_dict_keys = data_dict.Keys.OfType<string>().ToList();
foreach (Dictionary<string, Dictionary<(string, string), object>> datasets in dict_coll.Values) // datasets= Dictionary<string, Dictionary<(string, string), object>>>no need for specified types with hashtable but have to cast the value KeyValuePair<string, Dictionary<string, Dictionary<(string, string), object>>>
{
foreach (KeyValuePair<(string, string), object> i in guid_data)
{
if (i.Key.Item1.EndsWith("Parameter") & !guid_dict_keys.Contains(i.Key.Item2))//string.IsNullOrEmpty()//convert guidict to single string //guid_dict.Keys i.Key.Item2))
{
guid_dict[i.Key.Item2] = i.Value; //convert guid
}
}
foreach (Dictionary<(string, string), object> dataset in datasets.Values) //NULlMaybe/get dict(tuple,value) /KeyValuePair<(string, string), object>datasets.Value as Hashtable, KeyValuePair<(string, string), object>
{
// get survey/borehole/layer Ids
string target_layer_id = dataset[LAYER_ID].ToString();
string target_survey_id = dataset[SURVEY_ID].ToString(); //
string target_borehole_id = dataset[BOREHOLE_ID].ToString();//
//NULL
var finished = false;
while (!finished)
{
if (data_dict.ContainsKey(target_survey_id))
{
var survey_set = data_dict[target_survey_id];
var boreholes = survey_set["Boreholes"] as boreholes_dict;
if (boreholes.ContainsKey(target_borehole_id))
{
var borehole_set = boreholes[target_borehole_id] as borehole_id_dict;
layers_dict layers = new layers_dict();
layers = borehole_set["Layers"] as layers_dict;
if (layers.ContainsKey(target_layer_id))
{
{ }
finished = true;
}
else
{
finished = true;
}
}
else
{
boreholes.Add(target_borehole_id, new Dictionary<string, object>());
boreholes[target_borehole_id].Add("BoreholeParameter", new Dictionary<string, object>());
boreholes[target_borehole_id].Add("BoreholeSetting", new Dictionary<string, object>());
boreholes[target_borehole_id].Add("Layers", new Dictionary<string, object>());
//boreholes = new Dictionary<string,Dictionary<string,Dictionary<string,object>>
}
}
else
{
//Dictionary<string, object> survey_nested_dict = new Dictionary<string, object>();
data_dict.Add(target_survey_id, new Dictionary<string, Dictionary<string,object>>());
data_dict[target_survey_id].Add("SurveyParameter", new Dictionary<string, object>());
data_dict[target_survey_id].Add("SurveySetting",new Dictionary<string, object>());
data_dict[target_survey_id].Add("Boreholes", new Dictionary<string, object>());
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<string, object>();
try
{
val_dict = data_dict[target_survey_id][cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
}
}
string json_guid = JsonConvert.SerializeObject(guid_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test_guid_dict.json", json_guid);
string json = JsonConvert.SerializeObject(dict_coll, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test2.json", json);
string json_data = JsonConvert.SerializeObject(data_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test_data_dict.json", json_guid);
}
}
}
EDIT:
The following code has achieved the structure shown above in the question description. I hope it helps anyone who is stuck in this problem.
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
//If you declared nested dict as object you couldn't do any operations with it that are provided by Dictionary, only the ones valid for all objects.
Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>> dict_coll = new Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>>();
Dictionary<string, Dictionary<(string, string), object>> rows = new Dictionary<string, Dictionary<(string, string), object>>();
Dictionary<(string, string), object> row_usable = new Dictionary<(string, string), object>();
foreach (DataTable table in tables)
{
Dictionary<(string, string), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(string, string), object>();
foreach (DataColumn col in table.Columns)
{
string FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
string SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
rows.Remove("0");
rows.Remove("1");
rows.Remove("3");
List<(string, string)> row_Keys = new List<(string, string)>(row.Keys);
List<object> row_vals = new List<object>(row.Values);
row_usable = row_Keys.Zip(row_vals, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
}
dict_coll.Add(table.TableName.ToString(), rows);
}
var guid_data = rows.ElementAt(0).Value; //or use trygetvalue()
var SURVEY_ID = ("SurveyParameter", "SurveyId");
var BOREHOLE_ID = ("BoreholeParameter", "BoreholeId");
var LAYER_ID = ("Parameter", "LayerId");
Dictionary<string, object> guid_dict = new Dictionary<string, object>();
Dictionary<string,Dictionary<string, Dictionary<object, object>>> data_dict =
new Dictionary<string, Dictionary<string, Dictionary<object, object>>> ();
//Dictionary<string,object?> data_dict =
// new Dictionary<string,object?>();
//Hashtable data_dict = new Hashtable;
Hashtable restructured = new Hashtable();
restructured.Add("ParameterGuid", guid_dict);
restructured.Add("Data", data_dict);
List<string> guid_dict_keys = guid_dict.Keys.OfType<string>().ToList();
List<string> data_dict_keys = data_dict.Keys.OfType<string>().ToList();
foreach (Dictionary<string, Dictionary<(string, string), object>> datasets in dict_coll.Values) // datasets= Dictionary<string, Dictionary<(string, string), object>>>no need for specified types with hashtable but have to cast the value KeyValuePair<string, Dictionary<string, Dictionary<(string, string), object>>>
{
foreach (KeyValuePair<(string, string), object> i in guid_data)
{
if (i.Key.Item1.EndsWith("Parameter") & !guid_dict_keys.Contains(i.Key.Item2))//string.IsNullOrEmpty()//convert guidict to single string //guid_dict.Keys i.Key.Item2))
{
guid_dict[i.Key.Item2] = i.Value; //convert guid
}
}
foreach (Dictionary<(string, string), object> dataset in datasets.Values) //NULlMaybe/get dict(tuple,value) /KeyValuePair<(string, string), object>datasets.Value as Hashtable, KeyValuePair<(string, string), object>
{
// get survey/borehole/layer Ids
string target_layer_id = dataset[LAYER_ID].ToString();
string target_survey_id = dataset[SURVEY_ID].ToString(); //
string target_borehole_id = dataset[BOREHOLE_ID].ToString();//
//NULL
var finished = false;
while (!finished)
{
if (data_dict.ContainsKey(target_survey_id))
{
var survey_set = data_dict[target_survey_id];
var boreholes = survey_set["Boreholes"];
if (boreholes.ContainsKey(target_borehole_id))
{
var borehole_set = boreholes[target_borehole_id] as Dictionary<string, Dictionary<object, object>>;
//Hashtable layers = new Hashtable();
var layers = borehole_set["Layers"] as Dictionary<object, object>;
if (layers.ContainsKey(target_layer_id))
{
{ }
finished = true;
}
else
{
layers.Add(target_layer_id, new Dictionary<string, Dictionary<object, object>>
{
{"Parameter", new Dictionary<object, object>() },
{"LayerSetting", new Dictionary<object, object>()}
});
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>(); // Dictionary<string, object>();
try
{
var val_dicttt = layers[target_layer_id] as Dictionary<string, Dictionary<object, object>>; // extra variable for casting
val_dict = val_dicttt[cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
finished = true;
}
}
else
{
boreholes.Add(target_borehole_id, new Dictionary<string, Dictionary<object, object>>
{
{ "BoreholeParameter", new Dictionary<object, object>() },
{ "BoreholeSetting", new Dictionary<object, object>()},
{ "Layers", new Dictionary<object, object>() }
});
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>();
try
{
var val_dictt = boreholes[target_borehole_id] as Dictionary<string, Dictionary<object, object>>;
val_dict = val_dictt[cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
else
{
//1.use hashtable
//Dictionary<string, object> survey_nested_dict = new Dictionary<string, object>();
data_dict.Add(target_survey_id, new Dictionary<string, Dictionary<object, object>>());
data_dict[target_survey_id].Add("SurveyParameter", new Dictionary<object, object>()); //new Dictionary<object, object>()
data_dict[target_survey_id].Add("SurveySetting", new Dictionary<object, object>());
data_dict[target_survey_id].Add("Boreholes", new Dictionary<object, object>());
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>();// Dictionary<string, object>();
try
{
val_dict = data_dict[target_survey_id][cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
}
}
string json_guid = JsonConvert.SerializeObject(guid_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_guid_dict.json", json_guid);
string json = JsonConvert.SerializeObject(dict_coll, Formatting.Indented);
File.WriteAllText(#"D:\Data\test2.json", json);
string json_data = JsonConvert.SerializeObject(data_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_data_dict.json", json_data);
string json_final_data = JsonConvert.SerializeObject(restructured, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_restructured_data_dict.json", json_final_data);
}
}
}

Add days to timestamp

I need to add one day to unix timestamp. I got timestamp from API: unixDate = (string)result["dt"]; , result: 1617789600. But now I need to add one day to it. How can I do it?
public static List<Tuple<string, string, string, string>> euDataDaily(string url)
{
var aTuple = new List<Tuple<string, string, string, string>> { };
WebClient c = new WebClient();
var data = c.DownloadString(url);
JObject o = JObject.Parse(data);
string conditionCode="";
string unixDate = "";
string dayTemp="";
foreach (var result in o["daily"])
{
unixDate = (string)result["dt"];
dayTemp = (string)result["temp"]["day"];
foreach (var resultas in result["weather"])
{
conditionCode = (string)resultas["icon"];
}
}
List<Tuple<string, string>> icon = convertIcon(conditionCode);
foreach (var tuple in icon)
{
aTuple.Add(Tuple.Create(dayTemp, tuple.Item1, tuple.Item2, unixDate));
}
return aTuple;
}
JSON example:
{
"daily": [
{
"dt": 1595268000,
"sunrise": 1608124431,
"sunset": 1608160224,
"temp": {
"day": 278.14,
"min": 273.15,
"max": 279.4,
"night": 273.15,
"eve": 275.82,
"morn": 275.35
},
"weather": {
"clouds": 60,
"pop": 0.84,
"uvi": 2.41,
"icon": "cloudy.gif"
}
}
]
}
Thanks for your help!
Since you're already using JObject, you can cast it to an int instead of a string. If you swap out unixDate = (string)result["dt"]; for unixDate = (int)result["dt"];, you'll have the same number but in a int instead of a string. Then you can just add 86400(a day in seconds) and convert it back to a string with ToString().
Do note that, (int) cast does not work for normal strings, it's specific to JObject. If you try to do this on a normal string you'll get InvalidCastException. For normal strings go for int.Parse(or int.TryParse) instead.

Extracting variable data from JSON in C#

I have the following JSON which I need to manipulate into a different JSON format to be consumed by another process. My data is variable to some extent. Here is an example:
{
"subform_12": {
"multiline_2": "Subform 1 Long Text",
"listpicker_5": "High",
"alpha_1": "SubForm 1 Text"
},
"subform_13": {
"multiline_2": "Subform 2 Long Text",
"alpha_1": "SubForm 2 Text"
}
}
The variable part is the name of the json object (eg "subform_13") and the number and content of name pairs per object (eg "multiline_2": "Subform 1 Long Text").
What I need to do is convert each node into its own chunk of json, as in the following format:
{
"subform_13": [
[{
"fieldKey": "multiline_2",
"value": "Subform 2 Long Text"
},
{
"fieldKey": "alpha_1",
"value": "SubForm 2 Text"
}
]
]
}
Then separately:
{
"subform_13": [
[{
"fieldKey": "multiline_2",
"value": "Subform 2 Long Text"
},
{
"fieldKey": "alpha_1",
"value": "SubForm 2 Text"
}
]
]
}
So far I see that I can iterate thru the list as follows:
var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(
jsonString,
new Newtonsoft.Json.JsonSerializerSettings()
{
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
});
foreach (var item in json)
{
// I can see the "subform_13" and contents here in item , how do I generically extract them?
}
Any help appreciated.
Here is your Main method augmented with the ability to iterate through all values:
static void Main(string[] args)
{
var json = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string,JObject>>(
jsonString,
new Newtonsoft.Json.JsonSerializerSettings()
{
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
});
foreach (var item in json)
{
var key = item.Key; // "subform_12"
var val = item.Value;
Console.WriteLine(key+":");
foreach (var field in val)
{
var fieldKey = field.Key; // e.g. "multiline_2"
var fieldVal = field.Value; // e.g. "Subform 1 Long Text"
Console.WriteLine($"{fieldKey}={fieldVal.Value<string>()}");
}
Console.WriteLine();
}
}
I am just printing the values out; you would construct your new objects - for example as dynamic - using these values.
The output of my Main is:
subform_12:
multiline_2=Subform 1 Long Text
listpicker_5=High
alpha_1=SubForm 1 Text
subform_13:
multiline_2=Subform 2 Long Text
alpha_1=SubForm 2 Text
Hope it helps.
There are probably more elegant ways using linq, but here's code using a plain old JavaScriptSerializer from System.Web.Extensions.
There is a result dictionary, which you probably don't need if you want each object separated.
The json strings for each object is stored in the allJson list.
Similary, if you want the dictionary objects themselves you could just add seperated to a list during each iteration.
string s = "{\"subform_12\":{\"multiline_2\":\"Subform 1 Long Text\",\"listpicker_5\":\"High\",\"alpha_1\":\"SubForm 1 Text\"},\"subform_13\":{\"multiline_2\":\"Subform 2 Long Text\",\"alpha_1\":\"SubForm 2 Text\"}}";
JavaScriptSerializer ser = new JavaScriptSerializer();
Dictionary<string, object> obj = ser.DeserializeObject(s) as Dictionary<string, object>;
// combined dictionary of all results
Dictionary<string, object> result = new Dictionary<string, object>();
// an intermediary dictionary to house the results of each object
Dictionary<string, object> separated = new Dictionary<string, object>();
// a list to hold the json representation of each separate object
List<String> allJson = new List<string>();
foreach (KeyValuePair<string, object> src in obj)
{
Dictionary<string, object> children = (Dictionary<string, object>)src.Value;
Dictionary<string, object> t = new Dictionary<string, object>();
separated = new Dictionary<string, object>();
List<object> l = new List<object>();
foreach (KeyValuePair<string, object> child in children)
{
t.Add("fieldKey", child.Key);
t.Add("value", child.Value);
l.Add(t);
t = new Dictionary<string, object>();
}
separated.Add(src.Key, l.ToArray());
allJson.Add(ser.Serialize(separated));
result.Add(src.Key, l.ToArray());
}
// final string containing all transformed objects combined.
string combined = ser.Serialize(result);

Get Json Object From QueryString c#

The best I found was that available solutions at stack do not have answer for nested json object, they only address liner json values. But I have data to send is like
{ ob: { a: "78", b: { a: "gffg", h: {m:67, j:"fff"} } } }
If I want to do it in php i would just do
$json = $_POST['ob'];
$obj = json_decode($json);
But In c# I can'not do that. So I would appreciate any built-in method if available and I would love to be helped to fix my following code
I want to make a nested dictionary (I would prefer JOBject though). For ease of showing output I have serialized the result,
What result I have achieved yet from following code is
{"a":"78","ob":{},"ob.b":{"a":"gffg"},"ob.b.h":{"m":"67","j":"fff"}} but desired result is like sent data { "ob": { "a": "78", "b": { "a": "gffg", "h": {m:67, "j":"fff"} } } } Code is
string getJsonStringFromQueryString()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var nvc = Request.QueryString;
foreach (string key in nvc.Keys)
{
string[] values = nvc.GetValues(key);
string tempKey = key;
tempKey = tempKey.Replace("[", ".").Replace("]", "");
if (values.Length == 1)
dic.Add(tempKey, values[0]);
else
dic.Add(tempKey, values);
}
//It is giving me
{[ob.a, 78]}
{[ob.b.a, gffg]}
{[ob.b.h.m, 67]}
{[ob.b.h.j, fff]}
var result = makeNestedObject(dic);
var json = new JavaScriptSerializer().Serialize(result);
return json;
}
I am trying to add the leaf keys and their values as it is and all other keys as dictionary
Dictionary<string, object> makeNestedObject(Dictionary<string, object> qsDictionar)
{
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (string key in qsDictionar.Keys)
{
string temp = "";
if (key.Contains("."))
{
string[] ar = key.Split('.');
if (ar.Length > 2)
{
for (int i = 0; i < ar.Length - 1; i++)
{
temp = ar[0];
for (int j = 1; j <= i; j++)
{
temp += "." + ar[j];
}
//above is getting the previous key i want to use as dictionary, leaving the leaf key.
try
{
Dictionary<string, object> forTry = (Dictionary<string, object>)result[temp];
}
catch
{
result.Add(temp, new Dictionary<string, object>());
}
}
((Dictionary<string, object>)result[temp]).Add(ar[ar.Length - 1], qsDictionar[key]);
}
else
result.Add(ar[1], qsDictionar[key]);
}
}
return result;
}
Following method gives you complete solution for any json object.
string getJsonStringFromQueryString()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var nvc = Request.QueryString;
foreach (string key in nvc.Keys)
{
string[] values = nvc.GetValues(key);
string tempKey = key;
tempKey = tempKey.Replace("[", ".").Replace("]", "");
if (values.Length == 1)
dic.Add(tempKey, values[0]);
else
dic.Add(tempKey, values);
}
string vald = Request.QueryString["ob"];
var result = makeNestedObject(dic);
var json = new JavaScriptSerializer().Serialize(result);
return json;
}
Dictionary<string, object> makeNestedObject(Dictionary<string, object> qsDictionar)
{
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (string key in qsDictionar.Keys)
{
if (key.Contains("."))
{
List<string> keysList = key.Split('.').ToList();
Dictionary<string, object> lastAddedDictionary = result;
while (keysList.Count > 1)
{
if (!lastAddedDictionary.ContainsKey(keysList[0]))
{
Dictionary<string, object> temp = new Dictionary<string, object>();
lastAddedDictionary[keysList[0]] = temp;
lastAddedDictionary = temp;
}
else
lastAddedDictionary = (Dictionary<string, object>)lastAddedDictionary[keysList[0]];
keysList.RemoveAt(0);
}
lastAddedDictionary[keysList[0]] = qsDictionar[key];
}
else
{
result.Add(key, qsDictionar[key]);
}
}
return result;
}

How to create and populate a nested dictionary with three keys

I have a unique double corresponding to a variation of three strings. I want to populate a dictionary or something such that I can call something like dict[key1][key2][key3] and get the value.
I've tried a whole bunch of things like
Dictionary<string, Dictionary<string, double>> dict = new Dictionary<string, Dictionary<string, double>> {
{ "Foo", {"Bar", 1.2 } },
{ "Foo", {"Test", 3.4 } }
};
Which gives me syntax errors and errors like "Error 4 A namespace cannot directly contain members such as fields or methods"
And
Dictionary<double, Tuple<string, string>> dict = {
{1.23, "Blah", "Foo"}
};
Which gives me errors like "Error 1 Can only use array initializer expressions to assign to array types. Try using a new expression instead."
And
object dict = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, string>>();
dict["k1"]["k2"] = new Dictionary<string, string>();
dict["k1"]["k2"]["k3"] = 3.5;
Which gives me syntax errors and errors like "Error 2 Invalid token '"k1"' in class, struct, or interface member declaration"
How should I go about this? Thanks in advance.
![enter image description here][1]
Edit: Trying Jonesy's code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string[] grades = { "Grade 1", "Grade 5", "Grade 8", "ASTM A325", "316 Stainless", "Monel", "Brighton Best 1960" };
string[] sizes = { "#1", "2", "3", "4", "5", "6", "8", "10", "12", "1/4", "5/16", "3/8", "7/16", "1/2", "9/16", "5/8", "3/4", "7/8", "1", "1-1/8", "1-1/4", "1-3/8", "1-1/2" };
var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
dict["k1"]["k2"] = new Dictionary<string, double>();
dict["k1"]["k2"]["k3"] = 3.5;
public Form1()
{
InitializeComponent();
}
your last attempt is close, you want:
var dict = new Dictionary<string, Dictionary<string, Dictionary<string, double>>>();
dict["k1"] = new Dictionary<string, Dictionary<string, double>>();
dict["k1"]["k2"] = new Dictionary<string, double>();
dict["k1"]["k2"]["k3"] = 3.5;
you want var instead of object
(or Dictionary<string, Dictionary<string, Dictionary<string, double>>> if you like scrolling)
and your very last string should be a double.
As I understood, you have data and want to perform lookup in it. Why can't you just use some database for that purpose?
But if you really want to hardcode all values, you can. Just don't initialize dictionary manually, make simplifications - parse data in runtime.
Something like this. (I suppose, that you are novice in c# programming, so I've created new Console Application and copy-pasted all the code for your convenience)
public class Program
{
// harcode all data as string
const string RawData =
"k11,k12,k13=3.4;" +
"k21,k22,k23=4.42;" +
"k31,k32,k33=5.91;" +
"k41,k42,k43=8.14;" +
"k51,k52,k53=4.13;" +
"k61,k62,k63=5.4";
static void Main(string[] args)
{
// create dictionary from hardcoded string
var data = ParseData();
// use Tuple as key for data lookup
var value = data[Tuple.Create("k11", "k12", "k13")];
// check, that value equals expected one
Debug.Assert(value == 3.4);
}
private static IDictionary<Tuple<string, string, string>, double> ParseData()
{
var parsedData =
RawData
.Split(';')
.Select(ParseRow)
.ToDictionary(x => x.Item1, x => x.Item2);
return parsedData;
}
private static Tuple<Tuple<string, string, string>, double> ParseRow(string row)
{
var parts = row.Split('=');
var coefficients = ParseCoefficients(parts[0]);
var value = Double.Parse(parts[1], CultureInfo.InvariantCulture);
return Tuple.Create(coefficients, value);
}
private static Tuple<string, string, string> ParseCoefficients(string row)
{
var coeffs = row.Split(',');
var result = Tuple.Create(coeffs[0], coeffs[1], coeffs[2]);
return result;
}
}
As another simplification, you can use custom class as dictionary key instead of nested dictionaries. Write your own(pay attention, that it should override equality members Equals and GetHashCode), or use something from base class library. Tuple<string, string, string> is the perfect one.

Categories

Resources