Built-in Columns in JSON View Forms

SharePoint Online supports custom list view formatting with a funky little JSON DSL that is meant to allow customization without giving users full control over HTML or Javascript which is unsafe. This feature was added back in 2017.

The way it works, only displayed columns are allowed to be referenced in the custom JSON. Unfortunately, the feature owners never got around with supporting the “hidden” or “default” SharePoint columns like Created By or Last Modified. As a result, there is no way to show these columns at all in the “modern UI”. (As of 2024, this is still the case and it boggles the mind).

At work we have these “hack day”-style events that we call FHL (Fix. Hack. Learn.) where we are given some time to work on knocking out some of the little problems that get in the way of work, annoy us, QOL improvements, etc. This bug was bothering me because we are using some SharePoint lists internally to track stuff and we often want to see who created an item in the list, but there was no way to show it without some crazy hacks. (Dear feature owners: using a workflow to copy a default field into a totally redundant one on the same item is not my idea of a workaround.)

Long story short, I added hacky support for some of the default columns so they can be used in custom JSON views. The following columns should be able to be referenced now in SharePoint Online.

  • $Author — The “Created by” user. This a user object, e.g. [$Author.title] or [$Author.email]
  • $Editor — The “Modified by” user.
  • $Created — The date the item was created.
  • $Modified — The date the item was last modified.
  • $ID — The list item id.
  • $_UIVersionString — The “pretty” string for the current item version.

Here’s the most basic demonstration of adding a custom footer to the list view form for a document.

{
    "elmType": "div",
    "style": {
        "display": "block"
    },
    "children": [
        {
            "elmType": "div",
            "txtContent": "[$Author.title]"
        },
        {
            "elmType": "div",
            "txtContent": "[$Created]"
        },
        {
            "elmType": "div",
            "txtContent": "[$Editor.title]"
        },
        {
            "elmType": "div",
            "txtContent": "[$Modified]"
        },
        {
            "elmType": "div",
            "txtContent": "[$ID]"
        },
        {
            "elmType": "div",
            "txtContent": "[$_UIVersionString]"
        }
    ]
}

Here are a few posts from others online who have been struggling with this. Hopefully they run across this post and get unblocked.

Setting a Person field in SharePoint

This shouldn’t be this hard. The SharePoint team really needs to work on the programming model. This web API is bad bad.

For “reasons” I found myself needing to update a SharePoint list item to set the value of a Person field. It turns out that this is insanely annoying because what the ListItem API expects is the resolved User Id (it’s some rando number that’s assigned to the user when they access the site for the first time.) I’m working in a PowerAutomate flow and unfortunately that’s not a value that comes along with a user’s object. That would be too helpful.

If you try to use the Claims string to set the PersonFieldStringId field in a MERGE, it just doesn’t work. You get some terrible error message like Bad Gateway or something equally useless. Also, if you try to set through the navigation property like PersonField: { "Claims": ... }, that will succeed, but not actually work.

After being very frustrated and increasingly annoyed, I finally found someone who said to use the validateUpdateListItem method on the item. It worked. Apparently, this method “Validates and sets the values of the specified collection of fields for the list item.”

In case you find yourself on this site, wondering how this can all be so unnecessarily complicated, here’s the request you want to make.

URI: https://tenant.sharepoint.com/sites/MySite/_api/web/lists/GetByTitle('My List Name')/items(1234)/validateUpdateListItem
Method: POST
Headers: Content-Type=application/json;odata=verbose
Body:
{
"formValues": [
{
"FieldName": "Your_x0020_Field_x0020_Name",
"FieldValue": "[{'Key':'i:0#.f|membership|user@domain.com'}]"
}
]
}