public void ExpressionTest_False() { var isExpression = ExpressionParserUtilities.IsExpression("~Sample Value", out string expression); Assert.False(isExpression); Assert.Equal("", expression); }
public void ExpressionTest_True() { var isExpression = ExpressionParserUtilities.IsExpression("~(func(\"Sample Value\"))", out string expression); Assert.True(isExpression); Assert.Equal("func(\"Sample Value\")", expression); }
public void ExpressionTest_EmptyExpression_True() { var isExpression = ExpressionParserUtilities.IsExpression("~()", out string expression); Assert.True(isExpression); Assert.Equal("", expression); }
private void RecursiveEvaluate(JToken parentToken, string inputJson, JArray parentArray, JToken currentArrayToken) { if (parentToken == null) { return; } JEnumerable <JToken> tokens = parentToken.Children(); List <JToken> selectedTokens = null; Dictionary <string, JToken> tokensToReplace = null; List <JToken> tokensToDelete = null; List <string> loopProperties = null; JArray arrayToForm = null; List <JToken> tokenToForm = null; List <JToken> tokensToAdd = null; bool isLoop = false; foreach (JToken childToken in tokens) { if (childToken.Type == JTokenType.Array && (parentToken as JProperty).Name.Trim() != "#") { JArray arrayToken = childToken as JArray; List <object> itemsToAdd = new List <object>(); foreach (JToken arrEl in childToken.Children()) { object itemToAdd = arrEl.Value <JToken>(); if (arrEl.Type == JTokenType.String && arrEl.ToString().Trim().StartsWith("#")) { object value = ParseFunction(arrEl.ToString(), inputJson, parentArray, currentArrayToken); itemToAdd = value; } itemsToAdd.Add(itemToAdd); } arrayToken.RemoveAll(); foreach (object itemToAdd in itemsToAdd) { arrayToken.Add(itemToAdd); } } if (childToken.Type == JTokenType.Property) { JProperty property = childToken as JProperty; if (property.Name != null && property.Name == "#" && property.Value.Type == JTokenType.Array) { JArray values = property.Value as JArray; JEnumerable <JToken> arrayValues = values.Children(); foreach (JToken arrayValue in arrayValues) { if (arrayValue.Type == JTokenType.String && arrayValue.Value <string>().Trim().StartsWith("#copy")) { if (selectedTokens == null) { selectedTokens = new List <JToken>(); } selectedTokens.Add(Copy(arrayValue.Value <string>(), inputJson)); } if (arrayValue.Type == JTokenType.String && arrayValue.Value <string>().Trim().StartsWith("#replace")) { if (tokensToReplace == null) { tokensToReplace = new Dictionary <string, JToken>(); } string value = arrayValue.Value <string>(); tokensToReplace.Add(GetTokenStringToReplace(value), Replace(value, inputJson)); } if (arrayValue.Type == JTokenType.String && arrayValue.Value <string>().Trim().StartsWith("#delete")) { if (tokensToDelete == null) { tokensToDelete = new List <JToken>(); } tokensToDelete.Add(Delete(arrayValue.Value <string>())); } } } if (ExpressionParserUtilities.IsExpression(property.Value.ToString().Trim(), out string expression)) { expressionInterpreter.SetContext(currentArrayToken, parentArray, expression); try { var result = expressionInterpreter.Eval(expression); property.Value = new JValue(result); } catch (PathNotFoundException ex) { throw; } catch (Exception ex) { throw new Exception($"Could not execute expression: {expression}. Property: {property}.", ex); } } // TODO: Not required anymore // if (property.Name != null && property.Value.ToString().Trim().StartsWith("#") // && !property.Name.Contains("#eval") && !property.Name.Contains("#ifgroup") // && !property.Name.Contains("#loop")) // { // object newValue = ParseFunction(property.Value.ToString(), inputJson, parentArray, currentArrayToken); // // if (newValue != null && newValue.ToString().Contains("\"")) // { // try // { // JToken newToken = JToken.Parse(newValue.ToString()); // property.Value = newToken; // } // catch // { // property.Value = new JValue(newValue); // } // } // else // property.Value = new JValue(newValue); // } /* For looping*/ isLoop = false; if (property.Name != null && property.Name.Contains("#eval")) { int startIndex = property.Name.IndexOf("("); int endIndex = property.Name.LastIndexOf(")"); string functionString = property.Name.Substring(startIndex + 1, endIndex - startIndex - 1); object functionResult = ParseFunction(functionString, inputJson, null, null); JProperty clonedProperty = new JProperty(functionResult.ToString(), property.Value); if (loopProperties == null) { loopProperties = new List <string>(); } loopProperties.Add(property.Name); if (tokensToAdd == null) { tokensToAdd = new List <JToken> { clonedProperty }; } } if (property.Name != null && property.Name.Contains("#ifgroup")) { int startIndex = property.Name.IndexOf("("); int endIndex = property.Name.LastIndexOf(")"); string functionString = property.Name.Substring(startIndex + 1, endIndex - startIndex - 1); object functionResult = ParseFunction(functionString, inputJson, null, null); bool result = false; try { result = Convert.ToBoolean(functionResult); } catch { result = false; } if (result == true) { if (loopProperties == null) { loopProperties = new List <string>(); } loopProperties.Add(property.Name); RecursiveEvaluate(childToken, inputJson, parentArray, currentArrayToken); if (tokenToForm == null) { tokenToForm = new List <JToken>(); } foreach (JToken grandChildToken in childToken.Children()) { tokenToForm.Add(grandChildToken.DeepClone()); } } else { if (loopProperties == null) { loopProperties = new List <string>(); } loopProperties.Add(property.Name); } isLoop = true; } if (property.Name != null && property.Name.Contains("#loop")) { string strArrayToken = property.Name.Substring(6, property.Name.Length - 7); JsonReader reader = null; if (currentArrayToken != null && property.Name.Contains("#loopwithincontext")) { strArrayToken = property.Name.Substring(19, property.Name.Length - 20); reader = new JsonTextReader(new StringReader(JsonConvert.SerializeObject(currentArrayToken))); } else { reader = new JsonTextReader(new StringReader(inputJson)); } reader.DateParseHandling = DateParseHandling.None; JToken token = JObject.Load(reader); JToken arrayToken = null; if (strArrayToken.Contains("#") && !strArrayToken.Trim().StartsWith("#")) { int sIndex = strArrayToken.IndexOf("#"); string sub1 = strArrayToken.Substring(0, sIndex); int indexOfEndFunction = GetIndexOfFunctionEnd(strArrayToken); if (indexOfEndFunction > sIndex && sIndex > 0) { string sub2 = strArrayToken.Substring(indexOfEndFunction + 1, strArrayToken.Length - indexOfEndFunction - 1); string functionResult = ParseFunction(strArrayToken.Substring(sIndex, indexOfEndFunction - sIndex + 1), inputJson, parentArray, currentArrayToken).ToString(); strArrayToken = sub1 + functionResult + sub2; } } if (strArrayToken.Trim().StartsWith("#")) { arrayToken = ParseFunction(strArrayToken, inputJson, parentArray, currentArrayToken) as JArray; } if (arrayToken == null) { try { arrayToken = token.SelectToken(strArrayToken); if (arrayToken is JObject) { arrayToken = new JArray(arrayToken); } } catch { var multipleTokens = token.SelectTokens(strArrayToken); arrayToken = new JArray(multipleTokens); } } if (arrayToken == null) { arrayToForm = new JArray(); } else { JArray array = (JArray)arrayToken; IEnumerator <JToken> elements = array.GetEnumerator(); while (elements.MoveNext()) { if (arrayToForm == null) { arrayToForm = new JArray(); } JToken clonedToken = childToken.DeepClone(); RecursiveEvaluate(clonedToken, inputJson, array, elements.Current); foreach (JToken replacedProperty in clonedToken.Children()) { arrayToForm.Add(replacedProperty); } } } if (loopProperties == null) { loopProperties = new List <string>(); } loopProperties.Add(property.Name); isLoop = true; } /*End looping */ } if (childToken.Type == JTokenType.String && childToken.Value <string>().Trim().StartsWith("#") && parentArray != null && currentArrayToken != null) { object newValue = ParseFunction(childToken.Value <string>(), inputJson, parentArray, currentArrayToken); if (newValue != null && newValue.ToString().Contains("\"")) { try { JToken newToken = JToken.Parse(newValue.ToString()); childToken.Replace(new JValue(newValue)); } catch { } } else { childToken.Replace(new JValue(newValue)); } } if (!isLoop) { RecursiveEvaluate(childToken, inputJson, parentArray, currentArrayToken); } } if (selectedTokens != null) { foreach (JToken selectedToken in selectedTokens) { if (selectedToken != null) { JEnumerable <JToken> copyChildren = selectedToken.Children(); foreach (JToken copyChild in copyChildren) { JProperty property = copyChild as JProperty; (parentToken as JObject).Add(property.Name, property.Value); } } } } if (tokensToReplace != null) { foreach (KeyValuePair <string, JToken> tokenToReplace in tokensToReplace) { JToken selectedToken = (parentToken as JObject).SelectToken(tokenToReplace.Key); if (selectedToken != null && selectedToken is JObject) { JObject selectedObject = selectedToken as JObject; selectedObject.RemoveAll(); JEnumerable <JToken> copyChildren = tokenToReplace.Value.Children(); foreach (JToken copyChild in copyChildren) { JProperty property = copyChild as JProperty; selectedObject.Add(property.Name, property.Value); } } if (selectedToken != null && selectedToken is JValue) { JValue selectedObject = selectedToken as JValue; selectedObject.Value = tokenToReplace.Value.ToString(); } } } if (tokensToDelete != null) { foreach (string selectedToken in tokensToDelete) { JToken tokenToRemove = parentToken.SelectToken(selectedToken); if (tokenToRemove != null) { tokenToRemove.Ancestors().First().Remove(); } } } if (tokensToAdd != null) { foreach (JToken token in tokensToAdd) { (parentToken as JObject).Add((token as JProperty).Name, (token as JProperty).Value); } } if (tokenToForm != null) { foreach (JToken token in tokenToForm) { foreach (JProperty childToken in token.Children()) { (parentToken as JObject).Add(childToken.Name, childToken.Value); } } } if (parentToken is JObject) { (parentToken as JObject).Remove("#"); } if (loopProperties != null) { foreach (string propertyToDelete in loopProperties) { (parentToken as JObject).Remove(propertyToDelete); } } if (arrayToForm != null) { parentToken.Replace(arrayToForm); } }