Serialize C# dynamic object to JSON object to be consumed by javascript - c#

Based on the example c# dynamic with XML, I modified DynamicXml.cs and parsed my xml string.
the modified part is as follows
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
if (binder.Name == "Controls")
result = new DynamicXml(_elements.Elements());
else if (binder.Name == "Count")
result = _elements.Count;
else
{
var attr = _elements[0].Attribute(
XName.Get(binder.Name));
if (attr != null)
result = attr.Value;
else
{
var items = _elements.Descendants(
XName.Get(binder.Name));
if (items == null || items.Count() == 0)
return false;
result = new DynamicXml(items);
}
}
return true;
}
The xml string to parse:
"< View runat='server' Name='Doc111'>" +
"< Caption Name='Document.ConvertToPdf' Value='Allow Conversion to PDF'></ Caption>" +
"< Field For='Document.ConvertToPdf' ReadOnly='False' DisplayAs='checkbox' EditAs='checkbox'></ Field>" +
"< Field For='Document.Abstract' ReadOnly='False' DisplayAs='label' EditAs='textinput'></ Field>" +
"< Field For='Document.FileName' ReadOnly='False' DisplayAs='label' EditAs='textinput'></ Field>" +
"< Field For='Document.KeyWords' ReadOnly='False' DisplayAs='label' EditAs='textinput'></ Field>" +
"< FormButtons SaveCaption='Save' CancelCaption='Cancel'></ FormButtons>" +
"</ View>";
dynamic form = new DynamicXml(markup_fieldsOnly);
is there a way to serialize the content of this dynamic object(name value pairs inside dynamic) form as JSON object and sent to client side(browser)?

I've heard Json.Net works pretty well, though I've never used it myself.

Related

Find element in json file

I have JSON file like below, and I want to find a specific string or list of strings in this file.
I need to know if the values are in this file:
{
"naglowek": {
"dataGenerowaniaDanych": "20200107",
"liczbaTransformacji": "5000",
"schemat": "RRRRMMDDNNNNNNNNNNBBBBBBBBBBBBBBBBBBBBBBBBBB, gdzie R to cyfra roku, M – miesiąca, D - dnia daty generowania pliku, N to cyfra NIPu, a B to cyfra rachunku bankowego"
},
"skrotyPodatnikowCzynnych": [
"0000023d01e60fa522c2535d37c93051bdb9bc74e31b824460cd743a66a5282abb45567e43f09cfb26cd454b75ee6d6b0dfa83ef26db33581510afa421c3d430",
"0000025fe2175d2639990a7918baf727c41bbf554b1a88b679e32f3dc460c4dc44454b6a98417c31c4f2ee9e1c705ff951a1d7601553b327ec380213f2186a0f",
"00000cd37d8ded5c477552f61b647bcf9e6a967036823b7515b1e01e7fe3fe1854c470fb30f56beef1bc80d83d7350a53fe8677cb932f4f251837a767e0f8d63",
"00000d939549219dd4cd795c9b9680a3e5147791b1ddc4148f3463d6b3aa22849bcc30729cc60fc1282977d52d635c70d353f450c2abaef22f7d22439ac7b6e6",
"00001df757bb678d654308b1137c7dc8381d0457043009f4fc63edab93b32f60e1f460375e7da6965dbfd58f447d173c4c6c42add0d3dac181816782cf297cd8",
"0000248aef22c8ebddebd272cdc03e023f1dca221a5c7a731ade2989f1996b00b440c7410d52b89ef6f7927608bed66ad42a230f8e2cf86b97037597640d1da0",
"00002c000cd48dc44e63fa56d314962ff16b08c2e135a4c5352261a8e1c6b6fed9fefa01f01494d554e3158039450811a727c32576656d80963ed7b81a3732e3",
"00003666894d6872169f1f5212ba30a7441580f90d115823ca2d9cb6c5aca6e58ce277943bb284dd52cd669e8f05adba8d406ea8fb81c3e26bfce46b1cf8f120",
"00003bb55a8f67914ff5553a42f2bf2c8456b4f5d1a140ffdb1069442122114c61ad7bcbc715b35862c9e4566a8ddfbe9d9ca25457daa4cda51cdd796252b770",
"000041debf38337bb23391ccc9624483370a4e2d63dc4634c4f7c8d9071e5337d65464e59feedebe082bb7cbf6bb0a132b92194be457c92b1111132a51c81dcf",
"00004c88c01bc05ed4aa0df33cdbbe41aa77d49f94a6c9ee35efe6a59eca5cdea735acff28f05fb3d960973227b27ec81444b9afe14323fd2fc53a991b42c6ce"]
}
I need to find in this file specific string (one of the hashes)
I tried this:
public bool FindInFile(string sha512, string filePath, string date)
{
JObject o1 = JObject.Parse(File.ReadAllText(filePath + date + ".json"));
// read JSON directly from a file
using (StreamReader file = File.OpenText(filePath + date + ".json"))
using (JsonTextReader reader = new JsonTextReader(file))
{
JObject o2 = (JObject)JToken.ReadFrom(reader);
IEnumerable<JToken> pricyProducts = o2.SelectTokens("[?($.skrotyPodatnikowCzynnych == " + sha512 + ")]");
}
return true;
}
This should do the trick
public bool FindInFile(string sha512, string filePath, string date)
{
var obj = JObject.Parse(File.ReadAllText(filePath + date + ".json"));
return obj["skrotyPodatnikowCzynnych"].Children().Values<string>().Contains(sha512);
}
if you are sure the file is a valid json and do not contain other fields, why bother parsing it ? just look for the strings in it...
Otherwise just use linq to see if the query you wrote yields Any result...
pricyProducts.Any()
If it does not return any results ever, just fix the query (which i think is wrong)...
https://www.newtonsoft.com/json/help/html/SelectToken.htm
o2.SelectTokens("[?($.skrotyPodatnikowCzynnych == " + sha512 + ")]")
probably should be
o2.SelectTokens("$.skrotyPodatnikowCzynnych[?(# == '" + sha512 + "')]"

How to get comment or description field .resx file C#

I would like to get the description field in a .resx field using C#, At the moment I can get the "value" field using:
public static String f_str_textoRecurso(String p_str_archivo, String p_str_key)
{
System.Resources.ResourceManager t_rsm =
new System.Resources.ResourceManager("Resources." + p_str_archivo,
System.Reflection.Assembly.Load("App_GlobalResources"));
String t_str = t_rsm.GetString(p_str_key);
if (t_str != null)
{
if (p_str_key.Equals(""))
{
t_str = p_str_archivo.Remove(0, 4) + "." + p_str_key;
}
}
else
{
t_str = p_str_archivo.Remove(0, 4) + "." + p_str_key;
}
return t_str;
}
But I need also get comment. Any ideas?
Here you go:
public string ReadResourceComment(XmlDocument doc, string FieldName)
{
if (doc != null && !string.IsNullOrEmpty(doc.InnerXml))
{
return doc.SelectSingleNode("root/data[#name='" + FieldName + "']")["comment"].InnerText;
}
return string.Empty;
}
Here is how to use it:
Read your file ( It's XML document )
Pass which node you wanna read its comment
Example:
XmlDocument doc = new XmlDocument();
string filePath = HttpContext.Current.Server.MapPath("~/[FileName].resx");
doc.Load(filePath);
string comment = ReadResourceComment(doc, "[NodeName]");
// In your case, use ( ReadResourceComment(doc, "ot_desdecontrato");

C# XML - XPath Query Builder - Dynamically Create a Query

I am trying to build a XPath Query Builder in order to have a generic code as portable as possible.
So far, this is what I came up with :
private static string XpathQueryBuilder (string NodeName,string AttributeName = null, string AttributeValue = null)
{
string XpathAttr = "";
if (AttributeName != null)
if (AttributeValue != null)
XpathAttr = "[#" + AttributeName + "='" + AttributeValue + "']";
else
XpathAttr = "[#" + AttributeName + "='*']";
return "//" + NodeName + XpathAttr;
}
The problem I see with this method though is that if I have more than one attribute or node that I would like to look for, this function won't work. Is there a way to create an XPath Query dynamically that could theorically accept any number of attributes and/or Nodes.
My priority is on having a function that accepts more than one attribute and attribute value as this is the more likely case than more than one node.
Thank you for your time!
You can use Dictionary<string,string> to make the function capable of receiving multiple attributes parameter :
private static string XpathQueryBuilder(string nodeName, Dictionary<string,string> attributes = null)
{
string xpathAttr = "";
if (attributes != null)
{
xpathAttr =
"[" +
String.Join(" and ",
attributes.Select(o =>
{
var attrVal = o.Value ?? "*";
return "#" + o.Key + "='" + attrVal + "'";
})
) + "]";
}
return "//" + nodeName + xpathAttr;
}
example usage :
var node = "Root";
var attrs = new Dictionary<string, string>
{
{"foo", "bar"},
{"baz", null},
};
var result = XpathQueryBuilder(node, attrs);
Console.WriteLine(result);
dotnetfiddle demo
output :
//Root[#foo='bar' and #baz='*']
You can use LINQ to XML.
It will allow you select any data that you want.
Also, if you need more generic solution, you can try to implement your own LINQ Provider for that.
The second way is more complicated than the first one, but as a result you will have more generic solution that will provide access to your xml file by LINQ chains and expressions (lambda etc).
A few links with examples for help:
http://weblogs.asp.net/mehfuzh/writing-custom-linq-provider
http://fairwaytech.com/2013/03/writing-a-custom-linq-provider-with-re-linq/
http://jacopretorius.net/2010/01/implementing-a-custom-linq-provider.html
https://aashishkoirala.wordpress.com/2014/03/10/linq-provider-1/
Have you tried using LINQ to XML?
using System.Linq;
using System.Xml;
using System.Xml.Linq;
String GUID = "something";
XElement profilesXel = XElement.Load("your xml file path");
XElement currProfile = (from el in profilesXel
where (String)el.Element("GUID") == GUID
select el).First();
....

Printing Contents of ExpandoObject to an Indented String

I am currently working on a program that takes JSON input and deserializes it using JSON.NET into a dynamic ExpandoObject. Then through a function, I want to dump it out into another textbox to show what it could possibly represent as C# objects. How would I indent my string to show my hierarchical ExpandoObject and take it from a flat list of data to a tree structure of data I can send to a textbox as a string?
Here is some of the code I am using:
if (tbxJSON.Text != "")
{
// Create an ExpandoObjectConverter in order to hold the dynamic parsed JSON.
var converter = new ExpandoObjectConverter();
dynamic convertedJSON = JsonConvert.DeserializeObject<ExpandoObject>(tbxJSON.Text, converter);
tbxCSharp.Text = "";
// Loop through the ExpandoObject and print out all of the values in the dynamic object using a recursive function.
foreach (var property in (IDictionary<string, object>)convertedJSON)
sb.Append(ExpandoToString(property.Value, property.Key));
// Set C# output to contents of StringBuilder.
tbxCSharp.Text = sb.ToString();
}
private string ExpandoToString(object propVal, string propName)
{
string retStr = "";
// If we are dealing with nested JSON
if (propVal.GetType() == typeof(ExpandoObject))
{
// Append this object type.
sb.Append(Indent(indentIdx) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
foreach (var prop in (IDictionary<string, object>)propVal)
{
if (prop.Value.GetType() == typeof(ExpandoObject))
sb.Append(ExpandoToString(prop.Value, prop.Key));
else
{
if (prop.Value.GetType() == typeof(List<dynamic>))
{
// TO DO
}
else
sb.Append(ExpandoToString(prop.Value, prop.Key));
}
}
}
else
retStr = propVal.GetType() + " : " + propName + " = " + propVal + Environment.NewLine;
return retStr;
}
Test JSON:
{"airline":"Oceanic","number":815,"departure":{"IATA":"SYD","time":"2004-09-22 14:55","city":"Sydney"},"arrival":{"IATA":"LAX","time":"2004-09-23 10:42","city":"Los Angeles"}}
You should supply your current indent as a parameter to the ExpandoToString() method and increment it any time it calls itself.
private string ExpandoToString(object propVal, string propName, int indent = 0)
{
...
// Append this object type.
sb.Append(Indent(indent) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
...
sb.Append(ExpandoToString(propVal, propName, indent + 1) ...);

Build XML file from XPathExpressions

I have a bunch of XPathExpressions that I used to read an XML file. I now need go the other way. (Generate an XML file based on the values I have.)
Here is an example to illustrate. Say I have a bunch of code like this:
XPathExpression hl7Expr1 = navigator.Compile("/ORM_O01/MSH/MSH.6/HD.1");
var hl7Expr2 = navigator.Compile("/ORM_O01/ORM_O01.PATIENT/PID/PID.18/CX.1");
var hl7Expr3 = navigator.Compile("/ORM_O01/ORM_O01.PATIENT/ORM_O01.PATIENT_VISIT/PV1/PV1.19/CX.1");
var hl7Expr4 = navigator.Compile("/ORM_O01/ORM_O01.PATIENT/PID/PID.3[1]/CX.1");
var hl7Expr5 = navigator.Compile("/ORM_O01/ORM_O01.PATIENT/PID/PID.5[1]/XPN.1/FN.1");
var hl7Expr6 = navigator.Compile("/ORM_O01/ORM_O01.PATIENT/PID/PID.5[1]/XPN.2");
string hl7Value1 = "SomeValue1";
string hl7Value2 = "SomeValue2";
string hl7Value3 = "SomeValue3";
string hl7Value4 = "SomeValue4";
string hl7Value5 = "SomeValue5";
string hl7Value6 = "SomeValue6";
Is there a way to take the hl7Expr XPathExpressions and generate an XML file with the corresponding hl7Value string in it?
Or maybe just use the actual path string to do the generation (instead of using the XPathExpression object)?
Note: I saw this question: Create XML Nodes based on XPath? but the answer does not allow for [1] references like I have on hl7Expr4.
I found this answer: https://stackoverflow.com/a/3465832/16241
And I was able to modify the main method to convert the [1] to attributes (like this):
public static XmlNode CreateXPath(XmlDocument doc, string xpath)
{
XmlNode node = doc;
foreach (string part in xpath.Substring(1).Split('/'))
{
XmlNodeList nodes = node.SelectNodes(part);
if (nodes.Count > 1) throw new ApplicationException("Xpath '" + xpath + "' was not found multiple times!");
else if (nodes.Count == 1) { node = nodes[0]; continue; }
if (part.StartsWith("#"))
{
var anode = doc.CreateAttribute(part.Substring(1));
node.Attributes.Append(anode);
node = anode;
}
else
{
string elName, attrib = null;
if (part.Contains("["))
{
part.SplitOnce("[", out elName, out attrib);
if (!attrib.EndsWith("]")) throw new ApplicationException("Unsupported XPath (missing ]): " + part);
attrib = attrib.Substring(0, attrib.Length - 1);
}
else elName = part;
XmlNode next = doc.CreateElement(elName);
node.AppendChild(next);
node = next;
if (attrib != null)
{
if (!attrib.StartsWith("#"))
{
attrib = " Id='" + attrib + "'";
}
string name, value;
attrib.Substring(1).SplitOnce("='", out name, out value);
if (string.IsNullOrEmpty(value) || !value.EndsWith("'")) throw new ApplicationException("Unsupported XPath attrib: " + part);
value = value.Substring(0, value.Length - 1);
var anode = doc.CreateAttribute(name);
anode.Value = value;
node.Attributes.Append(anode);
}
}
}
return node;
}

Categories