WorkMaze / JUST.net

JUST - JSON Under Simple Transformation (XSLT equivalent for JSON).
MIT License
174 stars 54 forks source link

Loop does not look in previous transformed result and always results in null evaluation. #294

Open JuanHattingh opened 10 months ago

JuanHattingh commented 10 months ago

Whenever I perform a fairly trivial transformation that contains a loop operation over a previous transformed result then it always results in a null evaluation.

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"
        }
      ]
    }
  ]
}

Transformer

{
  "filteredItems": "#valueof($.topLevelItems[?(@.selectable == true)])",
  "summary": {
    "#loop($..filteredItems)": {
      "name": "#currentvalueatpath($.name)"
    }
  },
  "aliasedItems": "#valueof($..filteredItems)"
}

Actual Output

{
  "filteredItems": {
    "name": "item2",
    "type": "someType",
    "selectable": true,
    "itemArray": [
      {
        "property1": "item2_value1",
        "property2": "item2_value2"
      }
    ]
  },
  **"summary"**: null,
  "aliasedItems": {
    "name": "item2",
    "type": "someType",
    "selectable": true,
    "itemArray": [
      {
        "property1": "item2_value1",
        "property2": "item2_value2"
      }
    ]
  }
}

Expected Output

{
  ...
  "summary": {
     "name": "item2"
  }
  ...
}

As you can see from the actual output, aliasedItems correctly references the value from a previous transformation by looking in the transformed, however when I use the same selector for the loop enumeration summary then it always looks inside of the root (input) object, which of course does not contain the transformed property and never inside the previous transformation, hence the result is always null.

Courela commented 10 months ago

Indeed it's a bug, but I've found one more problem. The filteredItems in transformer returns an object, not an array, so even if LookInTransformed evaluation mode was working inside loops, it would try to loop over object properties, thus trying to add name property more than once, which would result in an error.

I've managed to correct this, but the transformer would have to be like this:

{
    "filteredItems": [ "#valueof($.topLevelItems[?(@.selectable == true)])" ],
    "summary": {
        "#loop($.filteredItems)": {
            "name": "#currentvalueatpath($.name)"
        }
    },
    "aliasedItems": "#valueof($..filteredItems)" //only one dot here would work as well
}

Output:

{
    "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"
                }
            ]
        }
    ]
}

Loops always return an array, that's why the summary field come as an array.