Implemented with Carafe Add-on
Introduction
JSON is an ideal standard for passing data back and forth in FileMaker, but it’s not the easiest format to read or interact with. Large amounts of data and very structured notation can lead to simple mistakes causing a multitude of problems. What if we could integrate a tool into FileMaker that can help solve these issues?
What is JSONEditor?
JSONEditor is a browser-based tool to view, edit, format, and validate JSON. It has various modes such as a tree editor, a code editor, and a plain text editor. Learn more.
What is Carafe?
In case you’re not familiar already, Carafe is a bundle format with a supporting toolchain that simplifies the process of integrating JavaScript in FileMaker. It’s completely free and open-source, and we encourage you to use and add to it! Learn more.
Carafe Add-on / Bundle Installation
To use the Carafe JSONEditor bundle, first install the bundle into your FileMaker solution using either Carafe Kitchen or the Carafe Add-on. Learn more.
If you’re already using Carafe Kitchen or Carafe Add-on, you can download the JSONEditor bundle and import it: https://carafe.fm/bundle/jsoneditor-soliant/
Alternatively, you can search for “JSONEditor” directly in the Carafe Add-on Configurator.
Configuration
After installing the JSONEditor bundle, you should have sample data displaying in the web viewer. If not, please walk through the installation process again. Once you see sample data, we can begin the configuration process to bind the bundle to the specific fields and scripts in FileMaker required for our use case. To do so, we’ll need a script to marshal some JSON data from FileMaker and pass it to the bundle for display and/or editing. We can also configure other options in the bundle to change its behavior and/or call FileMaker scripts in order to get the JSON back to FileMaker to be persisted or used for anything a script needs JSON for.
Here are the JSONEditor bundle configuration options:
Option | Description | Default Value | Type | Optional |
---|---|---|---|---|
jsonValue | Initial data loaded into the JSONEditor. WARNING - Omitting this value will display sample data in the editor. | {} | object | false |
options | This object will be passed directly to the underlying JSONEditor package. See a couple of important options below and a link to the documentation which documents all of the possible options. | {} | object | true |
callback | Name of the FileMaker script to call after a change is made and the debounce delay has passed without an additional change. The script will be called and passed a script parameter of the jsonValue as well as anything in additionalCallbackParameters. | "" | string | true |
additionalCallbackParameters | Anything you want passed back to the script defined in the Callback option. | {} | object | true |
debounce | Number of milliseconds to wait after a change is made and the debounce delay has passed without an additional change. | 1000 | int | true |
style | Optional CSS that will be applied to the JSONEditor. | "" | string | true |
Base JSONEditor Package Options:
Package | Description | Default Value | Type | Optional |
---|---|---|---|---|
mode | Set the editor mode. Available values: 'tree' (default), 'view', 'form', 'code', 'text', 'preview' | "tree" | string | false |
modes | Create a box in the editor menu where the user can switch between the specified modes. Available values: see mode. Leaving this out will cause the drop-down menu not to be drawn, locking the JSONEditor in one mode. | [] | array | false |
Read more about the JSONEditor package complete documentation of all the available configuration options here. If you have any questions or would like to learn more, we encourage you to join the Carafe community here.
Example 1: Load and Save from a FileMaker field
Example Requirements:
- OnRecordLoad script trigger, display the JSONEditor with the JSON value from a FileMaker field.
- When the data in the web viewer is updated by the user, save the data back to the field in FileMaker.
Layout Setup:
Script Variables
$jsonValue: JSONEditorExample::jsonValue
$options:
JSONSetElement( "{}";
["mode"; "code"; JSONString];
["modes[0]"; "code"; JSONString];
["modes[1]"; "form"; JSONString];
["modes[2]"; "text"; JSONString];
["modes[3]"; "tree"; JSONString];
["modes[4]"; "view"; JSONString];
["modes[5]"; "preview"; JSONString]
)
$callback: “Save”
$additionalCallbackParameters:
JSONSetElement ( "" ; "id" JSONEditorExample::PrimaryKey ; JSONString )
Your script should look something like this:
Save Script referenced in the callback option.
Notice that line 7 goes to the web viewer by name. Be sure this matches the carafeWebViewerObjectName defined in the JSONEditor loader script.
Example 2: Adding schema validation
Additional Requirements:
- Configure with schema to validate the JSON in the JSONEditor
- Return a true/false flag when saving identifying the validity of the data
What is JSON Schema?
JSON schema allows you to validate the structure of your JSON data. Here’s some more info:
https://json-schema.org/understanding-json-schema/about.html#about
https://json-schema.org/understanding-json-schema/basics.html#basics
Layout Setup:
Update the OnRecordLoad trigger to call a copy of the Example 1 Loader script that we’ll reconfigure with schema options.
Script Variables:
The only change from Example 1 is that we use the following definition for $options. Here we’re adding an additional “schema” property to the options array. This property is an object that defines the rules for schema validation. The schema shown here is taken directly from the JSONEditor examples (https://github.com/josdejong/jsoneditor/blob/develop/examples/07_json_schema_validation.html). It defines both employee and job level schema.
$options:
JSONSetElement( "{}";
["mode"; "code"; JSONString]; // mode - initial mode of the JSONEditor
["modes[0]"; "code"; JSONString]; // modes - list of allowable modes
["modes[1]"; "form"; JSONString];
["modes[2]"; "text"; JSONString];
["modes[3]"; "tree"; JSONString];
["modes[4]"; "view"; JSONString];
["modes[5]"; "preview"; JSONString];
["schema.title"; "Employee"; JSONString]; // schema
["schema.description"; "Object containing employee details"; JSONString];
["schema.type"; "object"; JSONString];
["schema.properties.firstName.title"; "First Name"; JSONString];
["schema.properties.firstName.description"; "The given name."; JSONString];
["schema.properties.firstName.examples[0]"; "John"; JSONString];
["schema.properties.firstName.type"; "string"; JSONString];
["schema.properties.lastName.title"; "Last Name"; JSONString];
["schema.properties.lastName.description"; "The family name."; JSONString];
["schema.properties.lastName.examples[0]"; "Smith"; JSONString];
["schema.properties.lastName.type"; "string"; JSONString];
["schema.properties.gender.title"; "Gender"; JSONString];
["schema.properties.gender.enum[0]"; "male"; JSONString];
["schema.properties.gender.enum[1]"; "female"; JSONString];
["schema.properties.availableToHire.type"; "boolean"; JSONString];
["schema.properties.availableToHire.default"; False; JSONBoolean];
["schema.properties.age.description"; "Age in years"; JSONString];
["schema.properties.age.type"; "integer"; JSONString];
["schema.properties.age.minimum"; 0; JSONNumber];
["schema.properties.age.examples[0]"; 28; JSONNumber];
["schema.properties.age.examples[1]"; 32; JSONNumber];
["schema.properties.job.$ref"; "job"; JSONString];
["schema.required[0]"; "firstName"; JSONString];
["schema.required[1]"; "lastName"; JSONString];
["schemaRefs.job.title"; "Job description"; JSONString]; // schemaRefs - additional schema referenced from main schema
["schemaRefs.job.type"; "object"; JSONString];
["schemaRefs.job.required[0]"; "address"; JSONString];
["schemaRefs.job.properties.company.type"; "string"; JSONString];
["schemaRefs.job.properties.company.examples[0]"; "ACME"; JSONString];
["schemaRefs.job.properties.company.examples[1]"; "Dexter Industries"; JSONString];
["schemaRefs.job.properties.role.description"; "Job title."; JSONString];
["schemaRefs.job.properties.role.type"; "string"; JSONString];
["schemaRefs.job.properties.role.examples[0]"; "Human Resources Coordinator"; JSONString];
["schemaRefs.job.properties.role.examples[1]"; "Software Developer"; JSONString];
["schemaRefs.job.properties.role.default"; "Software Developer"; JSONString];
["schemaRefs.job.properties.address.type"; "string"; JSONString];
["schemaRefs.job.properties.salary.type"; "number"; JSONString];
["schemaRefs.job.properties.salary.minimum"; 120; JSONNumber];
["schemaRefs.job.properties.salary.examples[0]"; 100; JSONNumber];
["schemaRefs.job.properties.salary.examples[1]"; 110; JSONNumber];
["schemaRefs.job.properties.salary.examples[2]"; 120; JSONNumber]
)
Now that a schema is in place, you’ll notice that the JSONEditor will notify you in code mode when there are schema validation errors. When a schema is set, an additional “isValid” property will be populated in the callback parameter. This is a Boolean based on the validation of the current data with the supplied schema. If schema is not defined, isValid will be null.
Example 3: Remote schema validation
Additional Requirements:
- Configure with remote schema to validate the JSON in the JSONEditor
- Return isValid when saving the JSON data
JSON schemas can be shared for reuse. For example, JSON Schema Store (https://www.schemastore.org/json/) has 350 public JSON schemas available that you can use to validate your data.
One of the complications here is that schemas can reference other schemas, require multiple schemas, and can be nested. To overcome this, our Carafe bundle uses a special reference parser to gather all the dependencies from the passed schema before initializing the JSONEditor.
To point to url hosted JSON schema, simply replace the schema object with a string url to the schema definition.
Layout Setup:
Script Variables:
$options:
JSONSetElement( "{}";
["mode"; "code"; JSONString]; // mode - initial mode of the JSONEditor
["modes[0]"; "code"; JSONString]; // modes - list of allowable modes
["modes[1]"; "form"; JSONString];
["modes[2]"; "text"; JSONString];
["modes[3]"; "tree"; JSONString];
["modes[4]"; "view"; JSONString];
["modes[5]"; "preview"; JSONString];
["schema"; "https://json.schemastore.org/geojson.json"; JSONString] // schema
)
In example three, I have changed the schema property in the Example 3 Loader script to https://json.schemastore.org/geojson.json, which is the schema definition for a geolocation. I’ve purposely created a typo on line 7. By removing the XXX, you should see the JSONEditor update in a valid state.
Example File
Use in your own solution
The three examples we shared here should cover many of the use cases you may have for JSONEditor in your FileMaker solution. We’d love to hear what uses you have found for this new tool.