Xml serializing dynamic string to boolean - c#

Below is an instance of a simple job scheduler which parses xml dynamic strings to json:
XML
<Navigations>
<Navigation Name="facebook" Active ="0" ></Navigation>
</Navigations>
c#
List<NavigationData> nds = new List<NavigationData>();
foreach (object cnav in (IEnumerable)c.Navigations)
{
NavigationData nd = new NavigationData();
nd.Name = (string)((dynamic)cnav).Name;
nd.Active = XmlConvert.ToBoolean((string)((dynamic)cnav).Active); // 3
nds.Add(nd);
}
transitContent.NavigationData = JsonConvert.SerializeObject(nds);
The above program throws an exception at line 3 as:
failed to convert string to boolean with XMLConvert.ToBoolean
not able to recognize string with Convert.ToBoolean
An other type conversions possibele in this scenario? The expected result should be:
JSON
[
{
"Name": "facebook",
"Active": false
}
]

Well yes, "0" isn't a valid value for a Boolean. It sounds like you possibly want something like:
List<NavigationData> nds = new List<NavigationData>();
foreach (dynamic cnav in (IEnumerable)c.Navigations)
{
NavigationData nd = new NavigationData();
nd.Name = cnav.Name;
nd.Active = cnav.Active != "0";
nds.Add(nd);
}
transitContent.NavigationData = JsonConvert.SerializeObject(nds);
This is assuming that cnav will expose all properties as strings (as their execution-time type).

Related

C# dynamic object, modify properties based on string paths

The use case is pretty simple in concept. I receive a json payload that has two properties on the root level:
instructions
base
Instructions are set of instructions that I am supposed to apply on the base json object.
For eg - according to the below payload,
I am supposed to traverse to the widgets within defaultWidgets of the base property.
Then replace it completely with whatever is the value of patchedValue.
Input Payload:
{
"instructions": [
{
"patchedPath": "defaultWidget.widgets",
"patchedValue": false,
}
],
"base": {
"defaultWidget": {
"hash": "ktocle2l0u527",
"layout": "6|6",
"managerId": "defaultWidget",
"widgets": [
{
"managerId": "defaultWidget",
"widgetId": "invCreateWid7",
"type": "standard",
"manifestPath": "nexxe.standard-section#0.0.0-next.11",
"defaultInputManifestPath": "nexxe.input#0.0.1-alpha.49",
"title": "scannedInvoice",
"children": [
{
"name": "tom"
}
],
"hash": "ktocle2lrgps9",
"directives": ""
}
]
}
}
}
The result should be :
{
"base": {
"defaultWidget": {
"hash": "ktocle2l0u527",
"layout": "6|6",
"managerId": "defaultWidget",
"widgets": false
}
}
}
Code:
var stringPayload = "{ \"instructions\": [ { \"patchedPath\": \"defaultWidget.widgets\", \"patchedValue\": false, } ], \"base\": { \"defaultWidget\": { \"hash\": \"ktocle2l0u527\", \"layout\": \"6|6\", \"managerId\": \"defaultWidget\", \"widgets\": [ { \"managerId\": \"defaultWidget\", \"widgetId\": \"invCreateWid7\", \"type\": \"standard\", \"manifestPath\": \"nexxe.standard-section#0.0.0-next.11\", \"defaultInputManifestPath\": \"nexxe.input#0.0.1-alpha.49\", \"title\": \"scannedInvoice\", \"children\": [ { \"name\": \"tom\" } ], \"hash\": \"ktocle2lrgps9\", \"directives\": \"\" } ] } }}";
var parsedPayload = JsonConvert.DeserializeObject(stringPayload);
var baseJ = parsedPayload.GetType().GetProperty("instructions").GetValue(parsedPayload, null);
string jsonString = JsonConvert.SerializeObject(parsedPayload);
I am stuck on the very initial steps , I am getting:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Type.GetProperty(...) returned null.
This is what QuickWatch says:
What's returned by DeserializeObject in this case is JObject so to start with you can cast to it:
var parsedPayload = (JObject) JsonConvert.DeserializeObject(stringPayload);
Then grab instructions and target to change:
var instructions = (JArray) parsedPayload["instructions"]; // cast to JArray
var result = parsedPayload["base"];
Then we can go over instructions and apply them:
foreach (var instruction in instructions) {
// grab target path and value
var targetPath = (string) ((JValue)instruction["patchedPath"]).Value;
var targetValue = (JValue)instruction["patchedValue"];
// temp variable to traverse the path
var target = result;
foreach (var part in targetPath.Split('.')) {
target = target[part];
}
// replace the value
target.Replace(targetValue);
}
Now result contains what was in base with instructions applied.
With Json.NET you can do that like this:
var json = File.ReadAllText("sample.json");
var semiParsedJson = JObject.Parse(json);
var instructions = (JArray)semiParsedJson["instructions"];
var #base = semiParsedJson["base"];
foreach (var instruction in instructions)
{
var path = (string)instruction["patchedPath"];
var newValue = (string)instruction["patchedValue"];
var toBeReplaced = #base.SelectToken(path);
toBeReplaced.Replace(newValue);
}
JObject.Parse parses the json string
With the index operator [] we retrieve the two top level nodes. - One of them is an array (that's why there is an explicit JArray cast)
The other one is a JToken
We iterate through the array and retrieve the path and the newvalue
We use the SelectToken to get the desired node and then apply the replacement via the Replace method.
Please bear in mind that this solution is not bulletproof. You might need to change the indexer operator to TryGetValue to be able to check existence before you perform any operation on the JToken.
You also need to check that the patchedPath is valid at all.

JSON Data to dynamic (Anonymous type) conversion

I'm having trouble converting JSON data to a dynamic type definition. I've looked at JObject, JsonConvert serialize/deserialize and nothing works. The closest thing to making this work is JsonConvert.DeserializeAnonymousType but this requires a definition that matches the JSON. In my case, the JSON is quite complicated so I really need to convert an instance of the JSON to a fully anonymous, dynamic type.
dynamic rawjson = #"{ 'tags': { 'abcd' : '12345' },'properties': { 'desired': { 'PropOne' : '2345', 'PropTwo' : '6789' } } }";
#region reference object
dynamic reference = new
{
SomeName = $"xxxx",
initialTwin = new
{
tags = new { abcd = 12345 },
properties = new
{
desired = new
{
PropOne = "2345",
PropTwo = "6789"
}
}
}
};
#endregion
dynamic anonobject = JsonConvert.DeserializeAnonymousType(rawjson, reference.initialTwin);
dynamic testobject = new
{
SomeName = $"xxxx",
initialTwin = $"{anonobject}"
};
I need the "testobject" in the code above to look exactly like the "reference" object. Using the DesializeAnonymousType gets me very close but the definition would be very hard to create and maintain.
How can I get the same results working from an instance of JSON data without typing the definition for DeserializeAnonyousType? Is that possible?
I have tested the way below and it worked for me:
var anonobject = JsonConvert.DeserializeObject<ExpandoObject>(rawjson);
dynamic testobject = new
{
SomeName = $"xxxx",
initialTwin = anonobject
};
But since this is a dynamic object, you need to know the properties you may want to use.
Example:
Console.WriteLine(testobject.initialTwin.tags.abcd);

Error when trying to extract values from a Json Object C#

I have a Json string like below and this is only a small snippet. The number in quotation marks is a Unix Time which i will need to use to iterate over each object.
{
"result": {
"1534860000": [
"1534860000",
19,
41
],
"1534863600": [
"1534863600",
11,
16
],
"1534867200": [
"1534867200",
2,
5
]
}
}
But when I attempt to extract the data in the arrays I get an error:
System.InvalidOperationException: 'Cannot access child value on Newtonsoft.Json.Linq.JProperty.'
Code:
JObject jsonObj = JObject.Parse(response);
string unixTime = Helpers.ConvertToUnix(yesterday.AddHours(hour)).ToString();
foreach (var obj in jsonObj["result"])
{
var array = obj[unixTime]; //here is where the error occurs
}
Anyone able to shed some light on what I am missing?
If we simplify your example code a little to remove the unixTime element (let's just hardcode it for now), we end up with this:
JObject jsonObj = JObject.Parse(response);
string unixTime = "1534860000";
At this stage, we have jsonObj which refers to the root of the JSON object and has a single property of result. Repeating your foreach here for context:
foreach (var obj in jsonObj["result"])
{
var array = obj[unixTime]; //here is where the error occurs
}
You end up with obj referring to the JSON path of result.1534860000. The problem is you're then looking for a property 1534860000 at this JSON path (result.1534860000.1534860000), which does not exist.
You can just get the value directly, like so:
var array = obj["result"][unixTime]
Of course, this requires some error-checking for ensuring the path exists, etc, but it demonstrates the point.
After some help from Kirk Larkin I thought I would post a code snippet up.
JObject jsonObj = JObject.Parse(response);
int hour = 0;
string unixTime = Helpers.ConvertToUnix(yesterday.AddHours(hour)).ToString();
var array = jsonObj["result"][unixTime];
It now returns the contents of the array.

Convert JSON String to JSON Object c#

I have this String stored in my database:
str = "{ "context_name": { "lower_bound": "value", "upper_bound": "value", "values": [ "value1", "valueN" ] } }"
This string is already in the JSON format but I want to convert it into a JObject or JSON Object.
JObject json = new JObject();
I tried the json = (JObject)str; cast but it didn't work so how can I do it?
JObject defines method Parse for this:
JObject json = JObject.Parse(str);
You might want to refer to Json.NET documentation.
if you don't want or need a typed object try:
using Newtonsoft.Json;
// ...
dynamic json = JsonConvert.DeserializeObject(str);
or try for a typed object try:
using Newtonsoft.Json;
// single
Foo foo = JsonConvert.DeserializeObject<Foo>(str);
// or as a list
List<Foo> foos = JsonConvert.DeserializeObject<List<Foo>>(str);
This works
string str = "{ 'context_name': { 'lower_bound': 'value', 'pper_bound': 'value', 'values': [ 'value1', 'valueN' ] } }";
JavaScriptSerializer j = new JavaScriptSerializer();
object a = j.Deserialize(str, typeof(object));
there's an interesting way to achive another goal which is to have a strongly type class base on json with a very powerfull tools that i used few days ago for first time to translate tradedoubler json result into classes
Is a simple tool: copy your json source paste and in few second you will have a strongly typed class json oriented .
In this manner you will use these classes which is more powerful and simply to use.
You can try like following:
string output = JsonConvert.SerializeObject(jsonStr);
This works for me using JsonConvert
var result = JsonConvert.DeserializeObject<Class>(responseString);
If your JSon string has "" double quote instead of a single quote ' and has \n as a indicator of a next line then you need to remove it because that's not a proper JSon string, example as shown below:
SomeClass dna = new SomeClass ();
string response = wc.DownloadString(url);
string strRemSlash = response.Replace("\"", "\'");
string strRemNline = strRemSlash.Replace("\n", " ");
// Time to desrialize it to convert it into an object class.
dna = JsonConvert.DeserializeObject<SomeClass>(#strRemNline);
In a situation where you are retrieving a list of objects of a certain entity from your api, your response string may look like this:
[{"id":1,"nome":"eeee","username":null,"email":null},{"id":2,"nome":"eeee","username":null,"email":null},{"id":3,"nome":"Ricardo","username":null,"email":null}]
In this situation you may want an array of Jason objects and cycle through them to populate your c# variable. I've done like so:
var httpResponse = await Http.GetAsync($"api/{entidadeSelecionada}");
List<List<string[]>> Valores = new();
if (httpResponse.IsSuccessStatusCode)
{
//totalPagesQuantity = int.Parse(httpResponse.Headers.GetValues("pagesQuantity").FirstOrDefault());
//Aqui tenho que colocar um try para o caso de ser retornado um objecto vazio
var responseString = await httpResponse.Content.ReadAsStringAsync();
JArray array = JArray.Parse(responseString);
foreach (JObject objx in array.Children<JObject>())
{
List<string[]> ls = new();
foreach (JProperty singleProp in objx.Properties())
{
if (!singleProp.Name.Contains("_xyz"))
{
string[] val = new string[2];
val[0] = singleProp.Name;
val[1] = singleProp.Value.ToString();
ls.Add(val);
}
}
Valores.Add(ls);
}
}
return Valores;
I achieved this solution by the #Andrei answer.
This does't work in case of the JObject this works for the simple json format data. I have tried my data of the below json format data to deserialize in the type but didn't get the response.
For this Json
{
"Customer": {
"id": "Shell",
"Installations": [
{
"id": "Shell.Bangalore",
"Stations": [
{
"id": "Shell.Bangalore.BTM",
"Pumps": [
{
"id": "Shell.Bangalore.BTM.pump1"
},
{
"id": "Shell.Bangalore.BTM.pump2"
},
{
"id": "Shell.Bangalore.BTM.pump3"
}
]
},
{
"id": "Shell.Bangalore.Madiwala",
"Pumps": [
{
"id": "Shell.Bangalore.Madiwala.pump4"
},
{
"id": "Shell.Bangalore.Madiwala.pump5"
}
]
}
]
}
]
}
}
string result = await resp.Content.ReadAsStringAsync();
List<ListView11> _Resp = JsonConvert.DeserializeObject<List<ListView11>>(result);
//List<ListView11> _objList = new List<ListView11>((IEnumerable<ListView11>)_Resp);
IList usll = _Resp.Select(a => a.lttsdata).ToList();
// List<ListViewClass> _objList = new List<ListViewClass>((IEnumerable<ListViewClass>)_Resp);
//IList usll = _objList.OrderBy(a=> a.ReqID).ToList();
Lv.ItemsSource = usll;

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