Build table programmatically for export to/import from JSON? - c#

I am using EntityFramework, C# and MVC to build a web app. I need to create a dynamic table in RAM like this
COL1 | COL2 | COL3... etc.
1 | Val | Val
2 | Val | Val
I then need to be able to read/write it to JSON in the following format:
[
{id:1, COL1: "Val", COL2: "Val", COL3: "Val" },
{id:2, COL1: "Val", COL2: "Val", COL3: "Val" }
];
I need to be able to read and write the table to this format, dynamically add columns and rows easily.
I have tried using DataTable but that causes this error when it serializes:
Error: A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'.
Any recommendations would be appreciated.
EDIT: This is the code I used to build the table that causes the error, even when using JSON.NET serialization:
DataTable datatable = new DataTable();
datatable.Columns.Add("DBID");
datatable.Columns.Add("ROW");
datatable.Columns.Add("ID");
DataRow row = datatable.NewRow();
row["DBID"] = "Test";
row["ROW"] = "Test";
row["ID"] = "Test";
datatable.Rows.Add(row);
string json = JsonConvert.SerializeObject(datatable, Formatting.Indented); // <- Error here
return Content(json, "application/json");
EDIT 2 - SOLUTION:
string json = JsonConvert.SerializeObject(datatable, Formatting.Indented,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.None
}
);
Thanks alan and T.S. for pointing me in the right direction and everyone else who answered!

As mentioned in many other posts, you can always add a reference to JSON.NET which exposes the method below:
var json = JsonConvert.SerializeObject(dataTableToConvertToJSON,
Formatting.Indented);
Update:
Try this code instead. It should take care of the error you're getting:
var dataTableToConvertToJSON = JsonConvert.SerializeObject(dataTableToConvertToJSON,
Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
To return the Json as a string use this:
return json;
To return a Json object use this:
return Json(dataTableToConvertToJSON, JsonRequestBehavior.AllowGet);

Like a variant your table can be stored like this:
public class TestClass
{
public int Id { get; set; }
public Dictionary<string,string> CR { get; set; } //Columns And Rows
}
And then create a list of this class, which represent your table : List<TestClass> and then serialize or deserialize it with custom converter.
P.S: alan idea is better)

Since you are importing/exporting this data to/from JSON, how about doing this on client side using JavaScript, though I am not sure whether that is at all an option for you or not. However, doing this gymnastic with JavaScript supports your requirement of adding col/properties dynamically, if that is what you need absolutely.
Otherwise having a simple C# class and constructing a list with that class' objects and then serializing the list should also do the job.

Related

JToken Array to Data Table C#

I have a JSON result with the following structure:
{
"property1":1,
"property2":[[1,"A"],[2,"B"],[3,"C"],...] // Possible to get >10000 values
}
Using the above JSON data format, I am only interested to get the array values from the property2 which contains an array of array values and convert it to data table.
The above JSON result is coming from an external WEB API and here is what I have currently:
var jsonResponse = API.RetrieveData();
JObject json = JObject.Parse(jsonResponse);
JToken[] A = json["property2"].ToArray();
Logically, I can loop on the elements of Array [] A column by column and add it to the predesigned data table. My problem is that, upon using this, the performance will be affected as in most cases, the data that will be retrieved from the API is > 10000 values.
Is there any specific way to convert this kind of JSON Format to DataTable in c# with the most efficient way?
Thank you in advance.
I have Better and Fast approach for You
Step 1
Create a class that is similar to json structure
public class JsonClass
{
public string property1 { get ; set; }
public List<Dictionary<int,string>> property2 { get ; set; }
}
Step 2
Use Newtonsoft and deserialize json input to json match class
JsonClass jsonClass = JsonConvert.DeserializeObject<JsonClass>(jsonInputString);
Step 3
if you are using WPF just use
datatable.ItemSource = jsonClass ;
if you are using Winform then use BindingSource Component
BindingSource binding = new BindingSource();
binding.DataSource = jsonClass;
datatable.DataSource = binding;
Result might be
property1 | property2
---------------------------------------
"A" | Collection
Good luck

Is it possible to add fields with invalid characters to a .net AnonymousType?

I'm trying to send a JSON message to facebook that they call a game.achievement but I wanted to create the object using an AnonymousType before Posting. The problem is one of the fields is "game:points" (with the colon). As you can see I've used the # prefix for the object field but it doesn't work for the game:points field. It gets underlined in red and won't compile.
var paramsJson = new
{
privacy = new { value = "ALL_FRIENDS" },
#object = new
{
app_id = "my app id",
type = "game.achievement",
title = "Test",
#"game:points" = 100,
description = "Test",
image = "img.png"
}
};
I've tried many varieties of #, double quotes etc. Is it possible or do I need to just use a StringBuilder for this?
Why don't you just use a dictionary?
var postData = new Dictionary<string, object>
{
{"game:points", 100}
}
Presumably you're going to have to serialize your object to Post it regardless of how it's constructed. Serializing this to JSON would result in the same structure. Alternatively, just do as other's have suggested and create a class for your payload. You can then use Newtonsoft to indicate alternative names for serialization.
public class GameAchievement
{
[JsonProperty("game:points")]
public int Points {get; set;}
}

Deserializing JSON response without creating a class

From the result of an API call I have a large amount of JSON to process.
I currently have this
Object convertObj = JsonConvert.DeserializeObject(responseFromServer);
I am aware that I could do something like
Movie m = JsonConvert.DeserializeObject<Movie>(responseFromServer);
And then use it like
m.FieldName
m.AnotherField
//etc
Ideally I would like to do something like
var itemName = convertObj["Name"];
to get the first Name value for the first item in the list.
Is this possible, or do I have to create a class to deserialize to?
The reason I do not want to create the class is I am not the owner of the API and the field structure may change.
Edit.
Okay so I created the class as it seems the best approach, but is there a way to deserialize the JSON into a list?
var sessionScans = new List<SessionScan>();
sessionScans = JsonConvert.DeserializeObject<SessionScan>(responseFromServer);
Complains that it cannot convert SessionScan to generic list.
No need to use dynamic, you can simply use JToken which is already does what you expect:
var json = #"
{
""someObj"": 5
}
";
var result = JsonConvert.DeserializeObject<JToken>(json);
var t = result["someObj"]; //contains 5
With .NET 6, this can be done as below,
using System.Text.Json;
using System.Text.Json.Nodes;
string jsonString = #"some json string here";
JsonNode forecastNode = JsonNode.Parse(jsonString)!;
int temperatureInt = (int)forecastNode!["Temperature"]!;
Console.WriteLine($"Value={temperatureInt}");
//for nested elements, you can access as below
int someVal = someNode!["someParent"]["childId"]!.ToString();
Refer this MS docs page for more samples - create object using initializers, make changes to DOM, deserialize subsection of a JSON payload.
You can try with JObject.Parse :
dynamic convertObj = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = convertObj.Name;
string address = convertObj.Address.City;
The below example can deserialize JSON to a list of anonymous objects using NewtonSoft.Json's DeserializeAnonymousType method.
var json = System.IO.File.ReadAllText(#"C:\TestJSONFiles\yourJSONFile.json");
var fooDefinition = new { FieldName = "", AnotherField = 0 }; // type with fields of string, int
var fooListDefinition = new []{ fooDefinition }.ToList();
var foos = JsonConvert.DeserializeAnonymousType(json, fooListDefinition);
You can use Json.NET's LINQ to JSON API
JObject o = JObject.Parse(jsonString);
string prop = (string)o["prop"];
Use Newtonsoft.Json
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var json = "[{'a':'aaa','b':'bbb','c':'ccc'},{'a':'aa','b':'bb','c':'cc'}]";
var ja = (JArray)JsonConvert.DeserializeObject(json);
var jo = (JObject) ja[0];
Console.WriteLine(jo["a"]);
I had this problem working with unknown APIs then I decide to come over this problem using this approach, I'm writing down here my test case:
[TestMethod]
public void JsonDocumentDeserialize()
{
string jsonResult = #"{
""status"": ""INTERNAL_SERVER_ERROR"",
""timestamp"": ""09-09-2019 11:00:24"",
""message"": ""documentUri is required.""
}";
var jDoc = JsonDocument.Parse(jsonResult);
if (jDoc.RootElement.TryGetProperty("message", out JsonElement message))
{
Assert.IsTrue(message.GetString() == "documentUri is required.");
}
}
it worked for me because first I was looking to find a way to use dynamic type as it's mentioned in Azure Function HTTPTrigger. But I found this approach most useful and robust.
Microsoft Reference

Parsing JSON to Controller in MVC

I'm parsing a json which has 3 properties that have arrays as values, to my controller. I managed to save the json to a Dictionary, and now i need those 3 arrays to make a query to my database.
The setup is the following
public JsonResult FilterMultiselects(string json)
{
Dictionary<string, string[]> filters = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(json);
string[] lines = filters["lines"];
string[] countries = filters["countries"];
string[] users = filters["users"];
var query = ... //do my query which returns the results i desire
string result = JsonConvert.SerializeObject(query, Formatting.Indented,
new JsonSerializerSettings {
PreserveReferencesHandling = PreserveReferencesHandling.Objects
});
return Json(result, JsonRequestBehavior.AllowGet);
}
The problem im having is that when i get to the part in which i initialize those 3 arrays only the second one(countries) exists. The other two dont even create which makes no sense to me. Even thought i have not worked with Dictionaries(hashes) too much in C# it looks good.
Could anyone help me with what am i missing?
The json im parsing has the following look:
{
lines: ["line 1", "line 2"]
countries: ["England"]
users: []
}
The string my controller receives is:
"{\"lines\":[\"line 1\",\"line 2\"],\"countries\":[\"England\"],\"users\":[]}"
The dictionary gets created and has 3 keys that have the correct arrays as values.

Convert JSON to DataTable

I have JSON in the following format:
[
{"id":"10","name":"User","add":false,"edit":true,"authorize":true,"view":true},
{"id":"11","name":"Group","add":true,"edit":false,"authorize":false,"view":true},
{"id":"12","name":"Permission","add":true,"edit":true,"authorize":true,"view":true}
]
How can I convert that into a C# DataTable object as follows?
---------------------------------------------------------------------
ID | Name | Add | Edit | View | Authorize
---------------------------------------------------------------------
10 | User | true | true | true | true
11 | Group | true | true | true | true
12 | Permission| true | true | true | true
There is an easier method than the other answers here, which require first deserializing into a c# class, and then turning it into a datatable.
It is possible to go directly to a datatable, with JSON.NET and code like this:
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Deserialize your jsonstring to some class
List<User> UserList = JsonConvert.DeserializeObject<List<User>>(jsonString);
Write following extension method to your project
using System.ComponentModel;
public static DataTable ToDataTable<T>(this IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for(int i = 0 ; i < props.Count ; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}
Call extension method like
UserList.ToDataTable<User>();
One doesn't always know the type into which to deserialize. So it would be handy to be able to take any JSON (that contains some array) and dynamically produce a table from that.
An issue can arise however, where the deserializer doesn't know where to look for the array to tabulate. When this happens, we get an error message similar to the following:
Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1.
Even if we give it come encouragement or prepare our json accordingly, then "object" types within the array can still prevent tabulation from occurring, where the deserializer doesn't know how to represent the objects in terms of rows, etc. In this case, errors similar to the following occur:
Unexpected JSON token when reading DataTable: StartObject. Path '[0].__metadata', line 3, position 19.
The below example JSON includes both of these problematic features:
{
"results":
[
{
"Enabled": true,
"Id": 106,
"Name": "item 1",
},
{
"Enabled": false,
"Id": 107,
"Name": "item 2",
"__metadata": { "Id": 4013 }
}
]
}
So how can we resolve this, and still maintain the flexibility of not knowing the type into which to derialize?
Well here is a simple approach I came up with (assuming you are happy to ignore the object-type properties, such as __metadata in the above example):
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Linq;
...
public static DataTable Tabulate(string json)
{
var jsonLinq = JObject.Parse(json);
// Find the first array using Linq
var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
var trgArray = new JArray();
foreach (JObject row in srcArray.Children<JObject>())
{
var cleanRow = new JObject();
foreach (JProperty column in row.Properties())
{
// Only include JValue types
if (column.Value is JValue)
{
cleanRow.Add(column.Name, column.Value);
}
}
trgArray.Add(cleanRow);
}
return JsonConvert.DeserializeObject<DataTable>(trgArray.ToString());
}
I know this could be more "LINQy" and has absolutely zero exception handling, but hopefully the concept is conveyed.
We're starting to use more and more services at my work that spit back JSON, so freeing ourselves of strongly-typing everything, is my obvious preference because I'm lazy!
It can also be achieved using below code.
DataSet data = JsonConvert.DeserializeObject<DataSet>(json);
You can make use of JSON.Net here. Take a look at JsonConvert.DeserializeObject method.
I recommend you to use JSON.NET. it is an open source library to serialize and deserialize your c# objects into json and Json objects into .net objects ...
Serialization Example:
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": new Date(1230422400000),
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
json = File.ReadAllText(System.AppDomain.CurrentDomain.BaseDirectory + "App_Data\\" +download_file[0]);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
Here is another seamless approach to convert JSON to Datatable using Cinchoo ETL - an open source library
Sample below shows how to convert
string json = #"[
{""id"":""10"",""name"":""User"",""add"":false,""edit"":true,""authorize"":true,""view"":true},
{ ""id"":""11"",""name"":""Group"",""add"":true,""edit"":false,""authorize"":false,""view"":true},
{ ""id"":""12"",""name"":""Permission"",""add"":true,""edit"":true,""authorize"":true,""view"":true}
]";
using (var r = ChoJSONReader.LoadText(json))
{
var dt = r.AsDataTable();
}
Sample fiddle: https://dotnetfiddle.net/y0siCi
I solved it by the following - Used Pravin Pawar's answer below - for converting the JSON object to dt.
https://stackoverflow.com/a/11982180/504351
1)Send the JSON from Angular to C# controller method.
2)In C# Controller method -
convert the string data (JSON object) to a datatable.
DataTable dt = (DataTable)JsonConvert.DeserializeObject(data, (typeof(DataTable)));
3)Create a table in SQL Server database by parsing through rows and columns of the datatable dt
int dt_length = dt.Columns.Count;
Random rand = new Random();
string tablename = "Test" + rand.Next().ToString();
string query = "Create table " + tablename + " ( ";
for (int i = 0; i < dt_length; i ++)
{
if(i == dt_length -1)
{
query = query + dt.Columns[i].ColumnName + " varchar(max) ) ";
}
else
{
query = query + dt.Columns[i].ColumnName + " varchar(max), ";
}
}
4)Similarly insert each of the row data in the table created.
5)This helps to dynamically create a database table from JSON.

Categories