Skip to content

Anatomy of a PBI Inspector V2 rule

Nat Van Gulck edited this page Jul 15, 2025 · 11 revisions

:note: This wiki entry describes the structure of a rules file and individual rules. For details on PBI Inspector V2 operators used in the rules' logic part, see the Operators wiki entry.

Structure of a rules file

A PBI Inspector V2 rules file is written in JSON. A rules file starts by defining a "rules" array in which multiple rules can be defined as follows:

{
   "rules": [ ... ]
}

Each rule object has the following properties:

{
    "id": "A unique identifier of your choice for the rule",
    "name": "A name that is shown in HTML results with wireframe images.",
    "description": "Details to help you and others understand what this rule does",
    "logType": "Optional. error|warning(default)",
    "itemType": "[fabricitemtype]. The Fabric item type that the rule applies to as referred to in the item's CI\CD .platform file, e.g. CopyJob, Lakehouse, Report, etc. or specify '*' to define a cross-Fabric items rule or 'json' to define a rule that applies to any JSON metadata file.",
    "disabled": true|false(default),
    "part": "Optional iterator. A Regular Expression to match one or more Fabric item file or folder path. Or, if the itemType is Report, then one of (case-sensitive) Report|ReportExtensions|Pages|PagesHeader|AllPages|Visuals|AllVisuals|MobileVisuals|AllMobileVisuals|Bookmarks|BookmarksHeader|AllBookmarks. If an array of multiple items is returned (such as when specifying 'Pages' or if a Regular Expression is used to match a file or folder path), the rule will apply to each item iteratively."
    "test": [
    //test logic
    ,
    //data variables (optional)
    ,
    //expected result
    ],
    "patch": 
    [
    //optional patch logic to fix the issue, currently only applicable to Power BI Reports
    ]
}

more on the 'part' iterator

As mentioned above the 'part' iterator can specify a regular expression to match on or more file or folder paths. Because PBI Inspector V2 is intended to run on both Windows and Linux, the respective folder separator characters have been substituted for the column character i.e. ':'. This makes for a simpler regular expression that is cross-platform and avoids having to use escape characters for each folder separator. Therefore you can specify:

"part":"folder1:.*:copyjob-content.json"

(or "part":"folder1:.*:copyjob-content\.json$" to escape the dot character)

to match a Fabric item path such as (on Windows):

C:\fabricproject\folder1\copyjob1.CopyJob\copyjob-content.json

or on Linux:

/home/fabricproject/folder1/copyjob1.CopyJob/copyjob-content.json

test definition

A test is defined as an array with three items as follows:

"test": [
  { logic },
  { optional - data mapping },
  { expected result }
]

test logic

PBI Inspector V2 uses JsonLogic to allow for the expression of complex logic itself written in JSON format. JSONLogic turns out to be ideally suited to the task of testing a Power BI report's JSON definition files and other Fabric item definitions' JSON files. See https://jsonlogic.com/ for more details. For Fabric file formats other than JSON, custom JSONLogic operators can be used to inspect these files and return a JSON formatted output.

While the test logic can be written to return a simple boolean result (i.e. true or false), it's often more useful in test results to see an array listing the items that failed the test such as the unique names of Power BI visuals; in which case the expected result would be an empty array i.e. [].

data mapping (optional)

The optional data mapping provides a way to define one or more named variable(s) as a literal value or a Json node returned by a Json pointer path expression, see https://docs.json-everything.net/pointer/basics/ for more details on syntax. This item can be omitted altogether so that a rule's test array may only have two items i.e. the logic and the expected result.

test expected result

The logic part of a test returns a JSON result, this could be true, false, a string, a number or an array or other JSON object. The test passes if it matches the expected result and fails otherwise.

For example, the following rule checks that, for each report page, certain charts have both axes titles displayed. The rule returns the names of failing visuals in an array. In this example, no data mapping is specified so the test array only has two items, namely the logic part and the expected result i.e. an empty array of failing visuals [].

{
      "id": "SHOW_AXES_TITLES",
      "name": "Show visual axes titles",
      "description": "Check that certain charts have both axes title showing, returns an array of visual names that fail the test.",
      "part": "Pages",
      "disabled": false,
      "test": [
        {
          "map": [
            {
              "filter": [
                {
                  "part": "Visuals"
                },
                {
                  "and": [
                    {
                      "in": [
                        {
                          "var": "visual.visualType"
                        },
                        [
                          "lineChart",
                          "barChart",
                          "columnChart",
                          "clusteredBarChart",
                          "stackedBarChart"
                        ]
                      ]
                    },
                    {
                      "or": [
                        {
                          "==": [
                            {
                              "var": "visual.objects.categoryAxis.0.properties.showAxisTitle.expr.Literal.Value"
                            },
                            "false"
                          ]
                        },
                        {
                          "==": [
                            {
                              "var": "visual.objects.valueAxis.0.properties.showAxisTitle.expr.Literal.Value"
                            },
                            "false"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            },
            {
              "var": "name"
            }
          ]
        },
        []
      ]
    }

patch

❗ Currently only Power BI Report parts such as Visuals patches are supported.

Optionally a rule can now also define a patch to fix items failing the test. For example a patch for the test above is as follows. The patch iterates through the failing visual names returned and fixes the "Visuals" part of the report definition by setting the "showAxisTitle" property to "true" for both the category and value axes:

"patch": [
        "Visuals",
        [
          {
            "op": "replace",
            "path": "/visual/objects/categoryAxis/0/properties/showAxisTitle/expr/Literal/Value",
            "value": "true"
          },
          {
            "op": "replace",
            "path": "/visual/objects/valueAxis/0/properties/showAxisTitle/expr/Literal/Value",
            "value": "true"
          }
        ]
      ]

A patch definition has the following structure and currently only supports report item types:

"patch": [
        "One of Report|ReportExtensions|Pages|PagesHeader|AllPages|Visuals|AllVisuals|MobileVisuals|AllMobileVisuals|Bookmarks|BookmarksHeader|AllBookmarks",
        [patch logic operator array]
      ]

The patch logic operator array is defined as per the JSON Patch specification at https://tools.ietf.org/html/rfc6902. PBI Inspector uses a .NET implementation of JSON Patch, see https://docs.json-everything.net/patch/basics/.

Therefore the full rule example including the patch is as follows:

    {
      "id": "SHOW_AXES_TITLES",
      "name": "Show visual axes titles",
      "description": "Check that certain charts have both axes title showing.",
      "part": "Pages",
      "disabled": true,
      "applyPatch": true,
      "test": [
        {
          "map": [
            {
              "filter": [
                {
                  "part": "Visuals"
                },
                {
                  "and": [
                    {
                      "in": [
                        {
                          "var": "visual.visualType"
                        },
                        [
                          "lineChart",
                          "barChart",
                          "columnChart",
                          "clusteredBarChart",
                          "stackedBarChart"
                        ]
                      ]
                    },
                    {
                      "or": [
                        {
                          "==": [
                            {
                              "var": "visual.objects.categoryAxis.0.properties.showAxisTitle.expr.Literal.Value"
                            },
                            "false"
                          ]
                        },
                        {
                          "==": [
                            {
                              "var": "visual.objects.valueAxis.0.properties.showAxisTitle.expr.Literal.Value"
                            },
                            "false"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            },
            {
              "var": "name"
            }
          ]
        },
        {
        },
        []
      ],
      "patch": [
        "Visuals",
        [
          {
            "op": "replace",
            "path": "/visual/objects/categoryAxis/0/properties/showAxisTitle/expr/Literal/Value",
            "value": "true"
          },
          {
            "op": "replace",
            "path": "/visual/objects/valueAxis/0/properties/showAxisTitle/expr/Literal/Value",
            "value": "true"
          }
        ]
      ]
    }

Rule File Examples

For full rule file examples see:

Clone this wiki locally