diff --git a/JUST.net/JsonTransformer.cs b/JUST.net/JsonTransformer.cs index 3a97c6f..a106e82 100644 --- a/JUST.net/JsonTransformer.cs +++ b/JUST.net/JsonTransformer.cs @@ -477,7 +477,6 @@ private void LoopOperation(string propertyName, string arguments, State state, r if (args.Length > 2) { previousAlias = (string)ParseFunction(args[2].Trim(), state); - state.CurrentArrayToken.Add(new LevelKey() { Key = previousAlias, Level = _levelCounter }, Context.Input); } else if (state.CurrentArrayToken.Any(t => t.Key.Key == alias)) { @@ -499,7 +498,7 @@ private void LoopOperation(string propertyName, string arguments, State state, r JToken arrayToken; var selectable = GetSelectableToken(state.GetAliasToken(previousAlias), Context); arrayToken = selectable.Select(strArrayToken); - + arrayToken = LookInTransformed(arrayToken, $"#valueof({args[0]})", state) as JToken; if (arrayToken != null) { //workaround: result should be an array if path ends up with array filter @@ -1106,7 +1105,7 @@ private object LookInTransformed(object output, string propVal, State state) output = ParseFunction(propVal, state); Context.Input = tmpContext; } - return output; + return output is Array ? new JArray(output) : output; } private object CallCustomFunction(object[] parameters) diff --git a/JUST.net/Transformer.cs b/JUST.net/Transformer.cs index 010141e..d42eb2c 100644 --- a/JUST.net/Transformer.cs +++ b/JUST.net/Transformer.cs @@ -122,31 +122,38 @@ public static object ifcondition(object condition, object value, object trueResu private static object ConcatArray(object obj1, object obj2) { JArray item = new JArray(); - JToken item1 = null, item2 = null; - for (int i = 0; i < ((object[])obj1).Length; i++) + var objArr1 = obj1 is JArray arr1 ? arr1.ToObject() : (object[])obj1; + for (int i = 0; i < objArr1.Length; i++) { - if (((object[])obj1)[i] is JValue) + if (objArr1[i] is JValue val) { - item1 = (JValue)((object[])obj1)[i]; - item.Add(item1); + item.Add(val); + } + else if (objArr1[i] is JObject obj) + { + item.Add(obj); } else { - item1 = (JObject)((object[])obj1)[i]; - item.Add(item1); + item.Add(JToken.FromObject(objArr1[i])); } } - for (int j = 0; obj2 != null && j < ((object[])obj2).Length; j++) + + var objArr2 = obj2 is JArray arr ? arr.ToObject() : (object[])obj2; + for (int j = 0; obj2 != null && j < objArr2.Length; j++) { - if (((object[])obj2)[j] is JValue) + + if (objArr2[j] is JValue val) + { + item.AddAfterSelf(val); + } + else if (objArr2[j] is JObject obj) { - item2 = (JValue)((object[])obj2)[j]; - item1.AddAfterSelf(item2); + item.Add(obj); } else { - item2 = (JObject)((object[])obj2)[j]; - item.Add(item2); + item.Add(JToken.FromObject(objArr2[j])); } } return item.ToObject(); @@ -160,13 +167,21 @@ public static object concat(object obj1, object obj2, JUSTContext context) { return str1.Length > 0 ? str1 + obj2?.ToString() : string.Empty + obj2.ToString(); } + else if (obj1 is JArray arr1) + { + return obj2 is JArray arr2 ? new JArray(arr1.Concat(arr2)).ToObject() : ConcatArray(arr1.ToObject(), obj2); + } return ConcatArray(obj1, obj2); } else if (obj2 != null) { if (obj2 is string str2) { - return str2.Length > 0 ? obj1?.ToString() + str2 : obj1.ToString() + string.Empty; + return str2; + } + else if (obj2 is JArray arr2) + { + return arr2.ToObject(); } return ConcatArray(obj2, obj1); } @@ -789,7 +804,7 @@ public static bool isstring(object val, JUSTContext context) public static bool isarray(object val, JUSTContext context) { - return val != null ? val.GetType().IsArray : false; + return val != null ? val is JArray || val.GetType().IsArray : false; } public static object ifgroup(bool isToInclude, object val) diff --git a/UnitTests/Arrays/LoopingTests.cs b/UnitTests/Arrays/LoopingTests.cs index 65ec48e..f9fb57f 100644 --- a/UnitTests/Arrays/LoopingTests.cs +++ b/UnitTests/Arrays/LoopingTests.cs @@ -360,7 +360,7 @@ public void LoopPathRefersAnotherLoopAlias() const string input = "{ \"orderItems\": [ { \"id\": \"1\", \"sku\": \"a\" }, { \"id\": \"2\", \"sku\": \"b\" }, { \"id\": \"3\", \"sku\": \"c\" } ], \"affectedItems\": [ 1, 2 ], \"test\": \"abc\" }"; const string transformer = "{ \"#loop($.affectedItems,affectedItems)\": { \"#loop($.orderItems,orderItems,root)\": { \"sku\": \"#currentvalueatpath($.sku)\", \"id\": \"#currentvalue(affectedItems)\" } }}"; - var result = new JsonTransformer().Transform(transformer, input); + var result = new JsonTransformer(new JUSTContext { EvaluationMode = EvaluationMode.Strict }).Transform(transformer, input); Assert.AreEqual("[[{\"sku\":\"a\",\"id\":1},{\"sku\":\"b\",\"id\":1},{\"sku\":\"c\",\"id\":1}],[{\"sku\":\"a\",\"id\":2},{\"sku\":\"b\",\"id\":2},{\"sku\":\"c\",\"id\":2}]]", result); } diff --git a/UnitTests/EvaluationModeTests.cs b/UnitTests/EvaluationModeTests.cs index c97fe68..bb19f72 100644 --- a/UnitTests/EvaluationModeTests.cs +++ b/UnitTests/EvaluationModeTests.cs @@ -26,5 +26,17 @@ public void MultipleLevelLookInTransformed() Assert.AreEqual("{\"level1\":{\"quoteId\":\"123\",\"notResolved\":null,\"level2\":{\"resolved1\":\"123\",\"level3\":{\"resolved2\":\"123\"}}}}", result); } + + [Test] + public void LoopsWithLookInTransformed() + { + const string input = "{ \"topLevelItems\": [ { \"name\": \"item1\", \"type\": \"someType\", \"selectable\": false, \"itemArray\": [ { \"property1\": \"item1_value1\", \"property2\": \"item1_value2\" } ] }, { \"name\": \"item2\", \"type\": \"someType\", \"selectable\": true, \"itemArray\": [ { \"property1\": \"item2_value1\", \"property2\": \"item2_value2\" } ] } ]}"; + const string transformer = "{ \"filteredItems\": [ \"#valueof($.topLevelItems[?(@.selectable == true)])\" ], \"summary\": { \"#loop($.filteredItems)\": { \"name\": \"#currentvalueatpath($.name)\" } }, \"aliasedItems\": \"#valueof($..filteredItems)\" }"; + + JUSTContext context = new JUSTContext { EvaluationMode = EvaluationMode.Strict | EvaluationMode.LookInTransformed }; + var result = new JsonTransformer(context).Transform(transformer, input); + + Assert.AreEqual("{\"filteredItems\":[{\"name\":\"item2\",\"type\":\"someType\",\"selectable\":true,\"itemArray\":[{\"property1\":\"item2_value1\",\"property2\":\"item2_value2\"}]}],\"summary\":[{\"name\":\"item2\"}],\"aliasedItems\":[{\"name\":\"item2\",\"type\":\"someType\",\"selectable\":true,\"itemArray\":[{\"property1\":\"item2_value1\",\"property2\":\"item2_value2\"}]}]}", result); + } } } \ No newline at end of file