JSON syntax

How JSON syntax is used in Protobi

Updated at September 29th, 2022

A Protobi project is specified by a JSON (JavaScript Object Notation) syntax which defines what elements exist and how they should be displayed. The beauty is that you can see and edit the actual code that defines your Protobi project.

JSON editor

For any element or group, press the circle or square icon and select "Edit JSON...." to edit element properties. JSON syntax is pretty simple, and the existing examples should help you figure out the logic.

The general pattern is {"key":"value"} pairs separated by commas. The key is always contained in quotes and the value may be a string, number, null, an array in square brackets or even another JSON object in curly braces.

All of the above attributes have default values, and can be set to null or "". Below is a list of allowable values. You can also download the Protobi JSON Reference.pdf.

"Elements" in project settings

For any Protobi project you can see and edit the complete JSON specification by selecting the "Elements" tab under project settings. The primary document is an array containing one JSON object for each element. This is for advanced users only, so be very careful if editing this directly. Below is an example of how JSON syntax can be used in "Elements" to define variables. 

Expand example

Define variables in "Elements"

In the simple example below, there are two elements, "Q1" representing a question in the survey, and "$root" representing the top of the survey document.

Here, "Q1" has an optional "format" attribute which specifies how raw values are to be formatted for display to the user, as an optional string title attribute.

[
    {
        "key": "Q1",
        "title": "Q1. What is your primary specialty?",
        "color":  "#9B6",
        "format": {
            "1": "Primary care",
            "2": "Allergy",
            "3": "Pulmonology",
            "4": "Otolaryngologist"
        }
    },
    {
        "key": "$root",
        "children": ["Q1"],
    }
]

We can extend the example to include a tab "profile" to be displayed to the user with a few defined admin variables:

[
    {
        "key": "Q1",
        "title": "Q1. What is your primary specialty?",
        "color":  "#9B6",
        "format": {
            "1": "Primary care",
            "2": "Allergy",
            "3": "Pulmonology",
            "4": "Otolaryngologist"
        }
    },
    {
        "key": "profile",
        "displayKey": "Profile",
        "children": [ "country", "source", "status"]
    },
    {
        "key": "status",
        "format": {
           "1": "Eligible",
           "2": "Invited",
           "3": "In progress",
           "4": "Terminated",
           "7": "Complete"
    },
    {
        "key": "$root",
        "children": ["profile", "Q1" ],
    }
]


Here, "country" is listed in the children of element "$root". Just naming a child is enough to define and create a default element. The attribute "country" defines constituent elements. But there is no entry defined with a key "country", so Protobi will create a default element {"key": "country"}. That element will in turn look in the data for a column named "country". If it finds such a column, it will display the values directly. Conversely, there is an entry with key "status" so Protobi will use that format to display the value in a human-readable format.



Attributes

key

Each element has a unique key that identifies it. Multiple groups can refer to the same key as a child element, and each group will point to the same element with the same properties. By default, the key appears in the element's header.

displayKey

Specifies a different string to display in the element's header. This might be handy if the survey define a column with key s0 but you would prefer the user to see Specialty instead. In this case you might have:

{
    "key": "s0",
    "displayKey": "Specialty"
}

title (string)

Longer text that appears below the element header. For instance, the element specialty might have the title

{
    "key": "s0",
    "displayKey": "Specialty",
    "title": "Doctor, what is your primary specialty?"
}

color heritable

The color of the element icon. It may be any CSS named color (e.g. "color": "gold") or hexadecimal color code (e.g."color": "#FA0")

{
    "key": "s0",
    "displayKey": "Specialty",
    "color": "#FA0",
    "color": "gold"

}

format heritable (object)

Translates raw values to human-readable strings for display. Underlying value is unchanged. Formats are directly comparable to SPSS value labels. Formats are specified as objects with the raw value as the key and the formatted string as the value, e.g.:

{
    "format": {
        "AD": "Andora",
        "AI": "Anguila",
        "AG": "Antigua",
        "AR": "Argentina",
        ...
    }
}

If no format is defined, then all raw values that appear in the data are displayed directly in the distribution. If a format is defined, then all formatted values appear in the distribution, whether or not they have data values. Values that exist in the data but are not defined in the format will appear under "Other".

You can toggle formatted value vs. raw value using the Format button.

display

Specify how the element should be displayed. Accepted values are:

  • "independent"
  • "checkbox"
  • "compact"

maxValue (number)

Reference value to calculate length of bars when numeric values are compacted to mean or median.

hidden (boolean)

Hides the entire element! To unhide the element, use the tree on the left to select the element, then press the "Advanced" button from the toolbar and select "Hide/unhide." You can also use the keyboard shortcut, Shift + D.

width (number)

Specify width in pixels.

height (number)

Specify height in pixels.

color (string)

Color code for element. Any CSS color string, such as "purple" or "#B69".

colors ("ascending"|"descending"|object)

Color scheme for element.

A special value like "descending" or "ascending" indicates the values are ordinal and code from shades of blue to green.

You can specify a hash of color codes for specific values, e.g.:


 {
    "colors": {
       "1": "red",
       "2": "orange",
       "3": "yellow"
    }
}

Data

field

By default, Protobi assumes that each element key refers to a data column with the same name. For instance, the element with key "s0" will look for a data column "s0".

You can override this using the field attribute. For instance the following defines an element "s0" which looks to the data column "spec" for its data:

{
    "key": "s0",
    "field": "spec"
}

element

Instead of using the field attribute, you can also override the data reference using the element attribute.  This attribute looks to the calculated element for its data. These calculation could be due to either transform or reformat.  For instance, the following element "s0_clone" would look for calculated data in "s0".

{
    "key": "s0_clone",
    "element": "s0"
}

type

Specify the data type for the element. Accepted values are:

  • null
  • ""
  • "string"
  • "number"
  • "date"
  • "empty"

If "type" is "number", the default is to sort by value, show means and auto-bin into ranges.

If "type" is "string", the default is to sort by frequency, not show means, and show a search bar if more than 10 values.

If "type" is "date", Protobi parses the values as Date values. Protobi will recognize any date format recognized by the browser. If you have a special date format, you can set the dateFormat attribute. See the Dates and times tutorial

If "type" is "empty", Protobi will not show data for this element at all. This is appropriate for groups of elements that have children but do not correspond to a data element themselves.

If "type" is "" or null, Protobi will make its best guess based on the available data.

dateFormat (string)

Specify a date format so that Protobi can parse the string values as dates. You can enter any format recognized moment.js, see this link for a complete syntax.

For instance, if your date looks like "Monday April 9, 2018" you can specify "dateFormat": "dddd MMM D, YYYY"

split (string|"word"|"letter")

Specifies a delimiter to split each responses into an array of values. You can enter a specific delimiter, such as a comma (","), semicolon (";") or pipe ("|").

For instance, each response may be a list of the respondent's favorite pizza toppings separated by commas.

    {
        "toppings": "s0",
        "split": ","
    }

You can also enter a special values like "word" which will intelligently break at all word and sentence boundaries, like spaces, periods, semicolons, and line breaks and drop some punctuation marks like "?" and "!". This is particularly useful when creating Word clouds

Setting "split": "letter" will split the string into individual characters. Not that you would but you could.

roundby (number|string|array) heritable

Specify bin size for grouping numeric values for analysis. Acceptable values are:

  • 0 no binning at all
  • number specify linear bin size, e.g. 10
  • array specify linear bin size, e.g. [1,5,10,25,50,100]
  • "auto" auto-guess bin size based on distribution
  • "log" logarithmic bins based on powers of 10

weight heritable

Specific a weight value for this element. Accepted values are:

  • String name of a data field with weight values, e.g. "sales"
  • String key of an element which calculates a weight, e.g. "s0"
  • Numeric constant to use as a weight, e.g. 1000
  • Default indicating no weight null

denominator (string) heritable

Divides response values by another data column or element. This is useful for transforming count responses into percentages. e.g.:

{
    "key": "s5a",
    "denominator": "s4"
}

Note that when denominator is set, Protobi automatically calculates the mean as a ratio average rather than a simple average, see the Ratios tutorial

transform (string)

If the element is a group, standard transforms calculates a summary value from children:

  • "sum" returns sum of children
  • "mean" returns mean of children
  • "median" returns median of children
  • "min" returns minimum of children
  • "max" returns maximum of children
  • "stdev" returns standard deviation of children
  • "squish" condenses multiple string values a single multi-value response
  • "compact" transforms multiple binary elements into a single multi-value response

There are a number of additional transforms for Date values (i.e. "type": "date"):

  • "minute" returns value to nearest minute
  • "hour" returns value to nearest hour
  • "day" returns value to nearest day
  • "month" returns value to nearest month
  • "year" returns value to nearest year
  • "dayofweek" returns name of day
  • "monthofyear" returns name of month

For groups, it is possible to "squish" responses from multiple columns into one multiple-response element. This is useful for questions like "List up to three reasons". It de-duplicates responses for each individual.

It is also possible to insert arbitrary JS code. The transform defines a function which is passed two objects, row represents the data row, and this represents the element itself. For instance:

{
    "key": "x-sqrt",
    "transform": "return Math.sqrt(row.x)"
}

string ("toLower"|"toUpper"|"titleCase"|"trim"|"deburr")

Specify any lodash.js string functions, including:

  • "toUpper" converts to upper case
  • "toLower" converts to lower case
  • "capitalize" converts first character to upper case and rest to lower case.
  • "deburr" converts to Latin characters and removes accent marks
  • "trim" removes leading and trailing spaces

reformat heritable (object)

An object mapping raw values to new values, { "raw": "new", ...}.

It works a lot like format except it actually transforms the values before analysis, and you can appy "format" to the results.

Reformat can be used to convert values like 99 into missing values:

{
    "reformat": {   "99":  "" }
}

Conversely, reformats can be useful to zero-fill missing values, e.g.

{
    "reformat": {  "":  0 }
}

Reformats are also used to recode verbatim responses. For instance, if a survey elicits respondent sex as a text open-ends, values might e recoded as :

{
    "reformat":{
        "Man": "M",
        "Male": "M",
        "male": "M",
        "Female": "F",
        "female": "F",
        "Woman": "F"
    }
}

The raw value is on the left, and is always written as a string. The new value on the right can be a number, boolean, null or string value.

Note that reformat is applied before format is applied and can be used in conjunction with other transformations.

ceiling heritable (number)

Bounds the distribution to this value or smaller. Useful for Winsorizing data.

floor heritable (number)

Bounds the distribution to this value or greater. Useful for Winsorizing data.

filter heritable (object)

A query expression that filters out all other values. This is useful for including only valid responses. Filter objects operate on the entire row, so the field name has to be specified. Constraints are specified in MongoDB query syntax.

A few examples:

  • {"QA5a": {"$in": [1,2,3,4,5]}} accepts rows where QA5a is in [1,2,3,4, 5]
  • {"QA5a": {"$nin": [-9, 98, 99]}} rejects rows where QA5a is -9, 98 or 99
  • {"QS4": {"$gte":0, "$lt": 100}} accepts rows where QA5a is 0 up to 99

Statistics

showMean (boolean) heritable

showSum (boolean) heritable

showMedian (boolean) heritable

showBasis (boolean) heritable

showMin (boolean) heritable

showMax (boolean) heritable

denominator (boolean) heritable

Groups

children (array)

list all sub-elements for the group. can use to create a shell for a new element. (advance use)

hideChildren (boolean)

When transform or compactto is used, children are usually hidden for display purpose. Use to hide/unhide children

compactto (number|string|array|null) heritable

Control how group is summarized in compact form:

  • A specific value, e.g. 1 for a top-box percentage.
  • An array, e.g. [1,2] for a top-N box percentage.
  • "$mean" for a summary of means.
  • "$sum" for a summary of sums.
  • "$min" for a summary of sums.
  • "$max" for a summary of sums.
  • "$median" for a summary of sums.
  • null for no summary.

compactto can also be specified for an independent element to display a single summarized value.

unique (boolean)

When transform to squished is used, "unique": false would count each value separately instead of collapse like items into a single value.

Heritable properties

Changes to these heritable properties propagate down to child elements within a group (and to their children...):

  • format,
  • reformat,
  • maxValue,
  • color,
  • weight,
  • showSum,
  • showMean,
  • showMedian,
  • showMin,
  • showMax,
  • showBasis,
  • denominator

Below is a partial list of attributes recognized by Protobi with their allowable values and a brief description:

Attribute Type Example Description




key
string "s1" Unique identifier for element. Required and immutable.
displayKey
string "S1" Override key for display.
title
string "Primary specialty" Additional description text.
field
string "s1x" Specify another data column as data source (default is "key")
element
key "s1x" Specify another element as data source, a
children
array  ["s1a","s1b","s1c"] List child elements. If not null, element is a group.
format
hash {"1":"PCP","2":"Neuro"} Format values for display after analysis.
reformat
object {"99":"", "7":0} Recode values prior to analysis.
color
string "gold"|"#FA0" CSS color for element.
colors
object {"1":"red","2":"yellow"} CSS colors for values. Can be "ascending" or "descending".
type
string "string"|"number"|"empty" Whether element values are numbers, string, or not applicable.
compactto
value or array 1 One or more summary values for top/bottom box percentages.
roundby
value or name 0|10|"auto"|"log" Bin range for numeric values.
transform
name "squish"|"sum"|"mean"|(fn) Specify standard transform function or code a custom function
split
string "," Split values at delimiter into a multiple response value
weight
number or key "ptwt"|1000 Weight frequencies by value of a data column or constant.
scale
number or key "s4"|100 Multiply values by a data column or constant.
denominator
number or key "s3"|100  Divide values by a data column or constant.
display
name null|"checkbox"|"compact" Specify how to display element as expanded, compact or group
hidden
boolean TRUE Hide element from tab
hideChildren
boolean TRUE Hide children (useful for groups with transform specified)
showBody
boolean FALSE Hide distribution (useful to show just summary stats)
heritable
boolean FALSE Whether changes to heritable properties propagate to children
showMissing
boolean FALSE Whether to include NA values in distribution percentages
chartType
name "VennDiagram" Specify alternative chart type (default is "BaselineBarChart")
chartOptions
boolean {"width":"480px"} Specify options specific to selected chartType
showStats
array of values or objects [[1,2],{label:"net",value:[6,7]} Additional custom statistics to show
follow
hash {"q1":["chartOptions.width"} Specify which elements and which attributes of them to follow

Was this article helpful?