Tutorial: Turning a Record's Header Data into a JSON Array

This tutorial walks through several ways to turn the header fields of a single Record into JSON, using the [JSONRECORD] variable, the [JSONRECORDOBJ] variable, and the Build JSON workflow action. Each example builds on the one before it, so if you are new to these tools start at Example 1 and work down.


All examples use the same sample Record so you can compare the output. It is an Invoice Record with these header fields and two line items:


Field

Value

Vendor

Acme Supply

InvoiceNumber

INV-1001

Amount

$1,234.50

IsPaid

Yes

PONumber

(empty)


Line items: Widget (qty 2, $500.00) and Gadget (qty 1, $234.50).

Before You Start: The Three Tools

[JSONRECORD] is a variable that dumps the Record's raw data rows exactly as DocMgt stores them. Every field becomes a DataName / DataValue pair. You cannot rename or type the values, but it takes zero setup.


[JSONRECORDOBJ] is a variable that builds one JSON object from the current Record, using property names you choose. 

The syntax is [JSONRECORDOBJ(Property^Field^Type^EmptyMode|Property^Field^Type^EmptyMode|...)]

Only the property name is required: [JSONRECORDOBJ(Vendor|Amount)] reads the Vendor and Amount fields and names the properties the same. Type is Text (default), Number, Boolean, or Raw. The variable works on header fields only and never hits the database, so it is safe to use anywhere variables are replaced: workflow actions, merge templates, E-forms, and REST bodies.


Build JSON (workflow action) builds one JSON object and either appends it to a JSON array in a Temp Variable or writes it as a single object. The object can come from a property mapping table or from JSON text. Because it appends, it is the tool for producing arrays, and because it runs inside loops it is the tool for nesting.


A rule of thumb for the whole tutorial: JSONRECORDOBJ gives you the object, Build JSON gives you the array, and the Raw type is how one goes inside the other.




Example 1: A DataName/DataValue Array with [JSONRECORD]

Use this when the receiving system just wants a list of field names and values and you do not care about the shape.


Step 1. Anywhere a variable is accepted (a Temp Variable action, a REST action body, a merge template), enter:

[JSONRECORD(|Vendor^InvoiceNumber^Amount^IsPaid^PONumber)]

The parameters are RecordID|HeaderFields|LineItemFields. Leaving the RecordID blank uses the current Record. Fields are separated by ^. Leave the field lists off entirely to return every field, including line items.


Step 2. Run it. The output is:


{"ID":123,"RecordID":123,"Data":[

  {"DataName":"Amount","DataValue":"$1,234.50","LineNumber":0},

  {"DataName":"InvoiceNumber","DataValue":"INV-1001","LineNumber":0},

  {"DataName":"IsPaid","DataValue":"Yes","LineNumber":0},

  {"DataName":"PONumber","DataValue":"","LineNumber":0},

  {"DataName":"Vendor","DataValue":"Acme Supply","LineNumber":0}

]}


What to notice. Every value is a string, including the amount with its currency symbol. Empty fields are included with an empty value. The array is wrapped in an object that also carries the Record ID. Line items, if you request them, appear in the same array with a LineNumber greater than zero. If any of those limitations matter, move on to Example 2.




Example 2: An Array Containing One Shaped Object

This is the most common real-world need: an API expects a list of invoices, even when you are sending just one, and it wants proper property names and numeric amounts.

Target output:


[{"Vendor":"Acme Supply","Invoice":"INV-1001","Amount":1234.5,"Paid":true}]


Step 1 - Clear the Temp Variable. Add a Multiple Temp Variables action. Set the variable name to Payload and the value to [DEL]. Build JSON always appends, so if this workflow step ever runs twice you would get two objects in the array. Clearing first makes the step safe to re-run.


Step 2 - Add a Build JSON action. Set options as follows - Temp Variable Name: Payload, Output: JSON array (appending to the Temp Variable), Object Source: JSON text.


Step 3 - Enter the object. In the JSON text box enter:

[JSONRECORDOBJ(Vendor|Invoice^InvoiceNumber|Amount^^Number|Paid^IsPaid^Boolean)]

Reading each mapping left to right: Vendor reuses the field name as the property name; Invoice^InvoiceNumber renames the field; Amount^^Number keeps the name but types it as a number (the double ^ means "same field name, skip to the type"); Paid^IsPaid^Boolean renames and types.


Step 4 - Use the result. Reference [DMTMP(Payload)] in your REST action body, Server Field Update, or wherever the JSON needs to go.


What to notice. The $1,234.50 became 1234.5 because the Number type strips currency formatting, and Yes became true. PONumber was not mapped so it does not appear. If a mapped field is empty it is written as null; add ^Y as the fourth segment to leave it out instead, for example PO^PONumber^^Y.




Example 3: An Array of Custom Per-Field Objects

Use this when the receiving system wants one entry per field but in its own shape, not DocMgt's DataName/DataValue shape. Here the target is a key/val/type triple:


[

  {"key":"Vendor","val":"Acme Supply","type":"string"},

  {"key":"Invoice","val":"INV-1001","type":"string"},

  {"key":"Amount","val":1234.5,"type":"number"}

]


Because each entry has a different property value but the same property names, you build it with one Build JSON action per field, all appending to the same array.


Step 1 - Clear the Temp Variable. Multiple Temp Variables action: Fields = [DEL].


Step 2 - Build the first entry. Add a Build JSON action. Temp Variable Name: Fields, Output :JSON array, Object Source: field mapping table. Click Add Property three times and fill in:

Property Name

Value

Type

Omit if Empty

key

Vendor

Text


val

[Vendor]

Text


type

string

Text


Note the difference between the first two rows: Vendor with no brackets is a literal label, [Vendor] with brackets is the field's value.


Step 3 - Build the second entry. Duplicate the action (the duplicate icon on the action keeps you from retyping it) and change the values: key: Invoice, val: [InvoiceNumber], type: string.


Step 4 - Build the third entry. Copy again: key: Amount, val: [Amount], type number.


Step 5 - Use the result with [DMTMP(Fields)].


What to notice. The property names and the extra literal type column are entirely yours; DocMgt is not imposing any shape. If you check Omit if Empty on the val row, an empty field drops the val property but still writes the entry; to skip the whole entry when a field is empty, put a filter on that Build JSON action instead.




Example 4: A Header Object That Contains Its Line Items

Use this when the receiving system wants a nested document: one invoice object with an array of lines inside it. This combines everything above and introduces the Raw type.


Target output:

[{

  "Vendor":"Acme Supply",

  "Invoice":"INV-1001",

  "Amount":1234.5,

  "Lines":[

    {"Item":"Widget","Qty":2,"Price":500},

    {"Item":"Gadget","Qty":1,"Price":234.5}

  ]

}]


The trick is to build the inner array first, then drop it into the outer object as Raw JSON.


Step 1 - Clear both Temp Variables. Multiple Temp Variables action with two rows: Payload = [DEL] and Lines = [DEL].


Step 2 - Add a Line Item Loop action so the next action runs once per line item.


Step 3 - Inside the loop, add a Build JSON action for the line. Temp Variable Name: Lines, Output: JSON array, Object Source: field mapping table:

Property Name

Value

Type

Item

[Description]

Text

Qty

[Quantity]

Number

Price

[LineAmount]

Number

Because this is inside the loop, it appends one object per line item. After the loop finishes, [DMTMP(Lines)] holds the two-element array.


Step 4 - After the loop, add the header Build JSON action. Temp Variable Nam:e Payload, Output: JSON array, Object Source: field mapping table:

Property Name

Value

Type

Vendor

[Vendor]

Text

Invoice

[InvoiceNumber]

Text

Amount

[Amount]

Number

Lines

[DMTMP(Lines)]

Raw

Raw tells Build JSON that the value is already JSON and should be inserted as-is rather than quoted as a string. Without it, Lines would come through as one long escaped string.


Step 5 - Use the result with [DMTMP(Payload)].


What to notice. The same pattern nests to any depth: each level is a Temp Variable built by the loop beneath it and pulled in as Raw by the level above. If this whole sequence itself sits inside a Search and Run Actions loop over many Records, move the Lines = [DEL] clear to be the first action inside that outer loop, so the line array resets for each Record while Payload keeps accumulating one object per Record.




Example 5: An Array with One Object per Record Using Search and Run Actions

Every example so far started from a single Record. Use this pattern when the receiving system wants a list of many Records, for example "all unpaid invoices for this vendor", each as its own object in one array.

Target output:

[

  {"Vendor":"Acme Supply","Invoice":"INV-1001","Amount":1234.5},

  {"Vendor":"Acme Supply","Invoice":"INV-1007","Amount":89},

  {"Vendor":"Acme Supply","Invoice":"INV-1012","Amount":2250}

]

The idea is the same as Example 4, just one level up: a Search and Run Actions action finds the Records and runs a Build JSON action once for each one, and because Build JSON appends, the array grows by one object per Record.


Step 1 - Clear the Temp Variable. Add a Multiple Temp Variables action with Invoices = [DEL]. This goes before the search so the array starts empty once, then accumulates across every Record the search returns.


Step 2 - Add a Search and Run Actions action. Set the Record Type and enter the search criteria, for example Record Type = Invoices, Vendor = [Vendor] and IsPaid = No. The actions you add inside this action run once for each Record found, and while they run, field variables such as [InvoiceNumber] refer to the found Record, not the one that started the workflow.


Step 3 - Inside the search, add a Build JSON action. Temp Variable Name: Invoices, Output: JSON array, Object Source: field mapping table:

Property Name

Value

Type

Vendor

[Vendor]

Text

Invoice

[InvoiceNumber]

Text

Amount

[Amount]

Number

If you prefer, set Object Source to JSON text and use [JSONRECORDOBJ(Vendor|Invoice^InvoiceNumber|Amount^^Number)] instead. The variable reads whichever Record is current, so inside the search that is the found Record.


Step 4 - After the search, use the result with [DMTMP(Invoices)]. Because the search action has finished, the Temp Variable holds the complete array and you are back on the original Record, so you can combine the two: a final Build JSON action with Output set to single JSON object and properties Vendor = [Vendor] (Text) and OpenInvoices = [DMTMP(Invoices)] (Raw) produces one object that carries the whole list.


What to notice. The clear step sits outside the search, which is the opposite of where the Lines clear went in Example 4. The rule is that a Temp Variable is cleared at the level above the loop that fills it: clear Invoices before the search because the search fills it, and if each found Record also needed its own line items, clear Lines as the first action inside the search because the Line Item Loop inside each Record fills it. Getting the clear on the wrong side of a loop is the most common mistake with these actions; if you end up with only the last Record, the clear is inside the loop, and if you end up with Records from a previous run, the clear is missing.


Going further. The search, the line item loop, and the Raw type combine freely. A search over Records where each Build JSON row pulls in [DMTMP(Lines)] as Raw, with a Line Item Loop filling Lines per Record, gives you a full nested document for every Record in one array. Each level is just a Temp Variable filled by the loop beneath it and cleared by the step above it.




Quick Reference

You want

Use

DataName/DataValue pairs, no setup

[JSONRECORD(|Field^Field)]

One object with your own property names

[JSONRECORDOBJ(Prop^Field^Type|...)]

An array (of anything)

Build JSON, Output = JSON array

One custom object per field

One Build JSON per field, same Temp Variable

Nest an array or object inside another

Build JSON property with Type = Raw

Reset an array before rebuilding

Multiple Temp Variables, value [DEL]

One object per Record from a search

Build JSON inside Search and Run Actions


Types available in both JSONRECORDOBJ and Build JSON: Text (default), Number (accepts $1,234.50 and ($500.00)), Boolean, and Raw (insert existing JSON unchanged). Empty values become null unless Omit if Empty is set. A Number that cannot be parsed becomes null rather than stopping the workflow; a Raw value that is not valid JSON stops the action, since that is a configuration error you want to see.