|
|
@ -11,43 +11,105 @@ |
|
|
|
void Main() |
|
|
|
void Main() |
|
|
|
{ |
|
|
|
{ |
|
|
|
string Rendered = JsonFromTemplate(Globals.strTemplate, Globals.strData); |
|
|
|
string Rendered = JsonFromTemplate(Globals.strTemplate, Globals.strData); |
|
|
|
|
|
|
|
Rendered.Dump(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// render adaptive card JSON |
|
|
|
// render adaptive card JSON |
|
|
|
public string JsonFromTemplate(string strTemplate, string strData) |
|
|
|
public string JsonFromTemplate(string strTemplate, string strData) |
|
|
|
{ |
|
|
|
{ |
|
|
|
string output = ""; |
|
|
|
string output = ""; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// replace instances of $data with x-data |
|
|
|
|
|
|
|
// this is to work around JSON Path limitations |
|
|
|
|
|
|
|
strTemplate = strTemplate.Replace("$","x-"); |
|
|
|
|
|
|
|
|
|
|
|
// first create JSON objects out of the input |
|
|
|
// first create JSON objects out of the input |
|
|
|
JObject Template = JObject.Parse(strTemplate); |
|
|
|
JObject template = JObject.Parse(strTemplate); |
|
|
|
JObject Data = JObject.Parse(strData); |
|
|
|
JObject data = JObject.Parse(strData); |
|
|
|
|
|
|
|
|
|
|
|
// body = array of jobjects |
|
|
|
// this is the old way - regex against the string |
|
|
|
|
|
|
|
// maybe do it a better way |
|
|
|
JArray TemplateBody = (JArray)Template["body"]; |
|
|
|
string queryString = @"..[?(@ =~ /\{(.+)?\}/)]"; |
|
|
|
|
|
|
|
|
|
|
|
// for each jobject in this array |
|
|
|
List<JToken> nodeList = template.SelectTokens(queryString).ToList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for each templated entity |
|
|
|
|
|
|
|
// retrieve entity from data JSON |
|
|
|
|
|
|
|
// if empty, remove entity |
|
|
|
|
|
|
|
foreach (JValue node in nodeList) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// get string literal for template entity |
|
|
|
|
|
|
|
string fulltext = node.Value<string>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// find the matching element in the data JSON |
|
|
|
|
|
|
|
// strip { and } from fulltext |
|
|
|
|
|
|
|
string cleantext = fulltext.Substring(1, fulltext.Length - 2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string searchString = "$." + cleantext; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// find the token in Data JSON |
|
|
|
|
|
|
|
// can be JValue or JArray |
|
|
|
|
|
|
|
JToken searchResult = data.SelectToken(searchString); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if this element exists in the data |
|
|
|
|
|
|
|
// and isn't $data |
|
|
|
|
|
|
|
// replace element with text from Data JSON |
|
|
|
|
|
|
|
// otherwise remove it |
|
|
|
|
|
|
|
if (searchResult != null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (searchResult.GetType() == typeof(JValue)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
string oldValue = node.Value<string>(); |
|
|
|
|
|
|
|
string newValue = oldValue.Replace(fulltext, ((JValue)searchResult.Value<string>()).ToString()); |
|
|
|
|
|
|
|
node.Value = node.Value<string>().ToString().Replace(oldValue, newValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (searchResult.GetType() == typeof(JArray)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// it's a JArray |
|
|
|
|
|
|
|
JArray searchArray = (JArray)searchResult; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (string item in searchArray) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
JObject newItem = new JObject((JObject)node.Parent.Parent); |
|
|
|
|
|
|
|
newItem["x-data"].Parent.Remove(); |
|
|
|
|
|
|
|
newItem["text"] = item; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
node.Parent.Parent.Parent.Add(newItem); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
node.Parent.Parent.Remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (fulltext.Contains("{x-")) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// this is handled differently |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// remove this node |
|
|
|
|
|
|
|
node.Parent.Parent.Remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// now find any empty arrays and nuke their parents |
|
|
|
|
|
|
|
// keep doing this until there are no more [] left in the JSON |
|
|
|
|
|
|
|
|
|
|
|
TemplateBody.Dump(); |
|
|
|
while (template.Descendants().OfType<JArray>().Where(v => v.Type == JTokenType.Array && v.Count() == 0).ToList().Count() > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<JArray> EmptyNodes = template.Descendants().OfType<JArray>().Where(v => v.Type == JTokenType.Array && v.Count() == 0).ToList(); |
|
|
|
|
|
|
|
foreach (JArray Node in EmptyNodes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Node.Parent.Parent.Remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JsonConvert.SerializeObject(template, Newtonsoft.Json.Formatting.Indented).Dump(); |
|
|
|
|
|
|
|
|
|
|
|
return output; |
|
|
|
return output; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// set up global statics |
|
|
|
// set up global statics |
|
|
|
public class Globals |
|
|
|
public class Globals |
|
|
|
{ |
|
|
|
{ |
|
|
|
public static Dictionary<string, string> Containers = new Dictionary<string, string> |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
{ "ActionSet", "actions"}, |
|
|
|
|
|
|
|
{ "Container", "items" }, |
|
|
|
|
|
|
|
{ "ColumnSet", "columns"}, |
|
|
|
|
|
|
|
{ "Column", "items"}, |
|
|
|
|
|
|
|
{ "FactSet", "facts"}, |
|
|
|
|
|
|
|
{ "Fact", ""}, |
|
|
|
|
|
|
|
{ "ImageSet", "images"} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static string strData = @" |
|
|
|
public static string strData = @" |
|
|
|
{ |
|
|
|
{ |
|
|
|
""template"" : |
|
|
|
""template"" : |
|
|
@ -278,4 +340,96 @@ public class Globals |
|
|
|
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"", |
|
|
|
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"", |
|
|
|
""version"": ""1.0"" |
|
|
|
""version"": ""1.0"" |
|
|
|
}"; |
|
|
|
}"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// How I used to do things with regex: |
|
|
|
|
|
|
|
// ========================================================================================================================================== |
|
|
|
|
|
|
|
// // get list of {template.refs} from JSON string |
|
|
|
|
|
|
|
// Match m = Regex.Match(strTemplate, @"\{(.+)?\}"); |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// //List<string> Elements = new List<string>(); |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// Dictionary<string,List<JToken>> elements = new Dictionary<string,List<JToken>>(); |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// while(m.Success) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// if (!elements.Keys.Contains(m.Value)) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// List<JToken> elementList = new List<JToken>(); |
|
|
|
|
|
|
|
// // find the JToken(s) containing this element |
|
|
|
|
|
|
|
// foreach (string el in Globals.CheckElements) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// IEnumerable<JToken> tempList = template.SelectTokens("$.." + el).Where(y => y.Value<string>().Contains(m.Value)); |
|
|
|
|
|
|
|
// elementList.AddRange(tempList); |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// // strip {} from element name |
|
|
|
|
|
|
|
// string searchTerm = m.Groups[1].Value; |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// string searchString = "$." + searchTerm; |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// // find the token in Data JSON |
|
|
|
|
|
|
|
// // can be JValue or JArray |
|
|
|
|
|
|
|
// var searchResult = data.SelectToken(searchString); |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// // if this element exists in the data |
|
|
|
|
|
|
|
// // and isn't $data |
|
|
|
|
|
|
|
// // replace element with text from Data JSON |
|
|
|
|
|
|
|
// // otherwise remove it |
|
|
|
|
|
|
|
// if (searchResult != null) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// if (searchResult.GetType() == typeof(JValue)) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // it's a JValue |
|
|
|
|
|
|
|
// // String.Replace value with SearchResult value as string |
|
|
|
|
|
|
|
// // Elements.Add(m.Value, elementList); |
|
|
|
|
|
|
|
// // for every element in elementList |
|
|
|
|
|
|
|
// // replace m.Value with SearchResult.Value.ToString() |
|
|
|
|
|
|
|
// foreach (JValue element in elementList) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// string oldValue = element.Value<string>(); |
|
|
|
|
|
|
|
// string newValue = oldValue.Replace(m.Value,((JValue)searchResult.Value<string>()).ToString()); |
|
|
|
|
|
|
|
// element.Value = element.Value.ToString().Replace(oldValue, newValue); |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// else if (searchResult.GetType() == typeof(JArray)) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // it's a JArray |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// else if (m.Value == "{x-data}") |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // this needs to be output as a list of data |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// else |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // what is this? |
|
|
|
|
|
|
|
// // find the token in the Template array and remove it |
|
|
|
|
|
|
|
// string nodeText = m.Groups[1].Value; |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// // search for all nodes containing this value in any of the keys found in CheckElements |
|
|
|
|
|
|
|
// // add to list FoundNodes |
|
|
|
|
|
|
|
// // build a search string |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// // Evaluates to .*\{item\.name}.* |
|
|
|
|
|
|
|
// string innerValue = Regex.Escape("{" + nodeText + "}"); |
|
|
|
|
|
|
|
// string regexString = $".*{innerValue}.*"; |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// string jsonPath = $"..[?(@ =~ /{regexString}/)]"; |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// List<JToken> FoundNodes = template.SelectTokens(jsonPath).ToList(); |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// foreach (JToken Node in FoundNodes) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // find node by path |
|
|
|
|
|
|
|
// // this is the value of the property |
|
|
|
|
|
|
|
// // parent is property |
|
|
|
|
|
|
|
// // grandparent is node |
|
|
|
|
|
|
|
// Node.Parent.Parent.Remove(); |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// |
|
|
|
|
|
|
|
// m = m.NextMatch(); |
|
|
|
|
|
|
|
// } |