JSON itself is a data interchange format that represents structured data as a collection of key-value pairs. It doesn’t inherently have the concept of records and field sets like you might find in a database. However, you can transform JSON data into a structure that EasyCatalog can import via a simple script.
You essentially break down each JSON object into separate records and represent the keys within each object as fields. Keep in mind that this transformation depends on the specific structure of your JSON data and the requirements of your application.
Here’s a simple script designed to handle a simply structured JSON File (Uses functions only available in the 2024 or later version of EasyCatalog).
--------------------------------------------------------------------------------------------------------- -- JSON 2024 Custom Data Provider. -- -- Only works in the 2024 version of EasyCatalog -- -- Key functions are called during data retrieval and update. The script is initialised and called on demand, -- as such it is statless and relies on the 'configration' settings passed form call to call to represent -- the data sources current settings. -- -- Data Source Creation -- During creation of a new data source the call sequence is as follows: -- 1. Initialize() - returns a table of default settings, which are [ersisted in the data sources datasource.xml file. -- 2. ConfigureUI(config) presents configuration settings to the user to allows modification (not called on InDesign Server) -- 3. Synchronize(datasource, config) - called after configuration to retreive a complete RECORDSET -- -- Data Source Updates -- SaveRecords(config, datasource, records) - is called when the user selects "Update Data Source". -- this is responisble for passing updates back and clearing the update flag. -- --------------------------------------------------------------------------------------------------------- -- -- Oct 2023 Created v1.0.0 -- --------------------------------------------------------------------------------------------------------- --[[ Example structure of JSON this sample is designed to load: { "products": [ { "id": "12345", "name": "Product A", "description": "This is Product A, a high-quality product.", "price": 19.99, "category": "Electronics", "stock": 50 }, { "id": "67890", "name": "Product B", "description": "Product B is a versatile and popular item.", "price": 29.99, "category": "Clothing", "stock": 100 }, { "id": "54321", "name": "Product C", "description": "Product C is a premium accessory.", "price": 39.99, "category": "Accessories", "stock": 25 } ] } ]]; -- This specifies the JSONPath to each 'record' in the resulting data local record_JSONPath = "$.products[*]" -- This specifies fields to extract from each record local fields_with_options = { { name = "id", jsonpath = "$.id", key = "true"}, { name = "name", jsonpath = "$.name"}, { name = "description", jsonpath = "$.description"}, { name = "price", jsonpath = "$.price"}, { name = "stock", jsonpath = "$.stock"} }; ------------------------------------------------------------------------------------------------------------------------ -- load_file ------------------------------------------------------------------------------------------------------------------------ function load_file(path) local file = io.open(path, "r"); if not file then return nil end local content = file:read "*a" -- *a or *all reads the whole file file:close(); return content end ------------------------------------------------------------------------------------------------------------------------ -- getActualScriptVersion ------------------------------------------------------------------------------------------------------------------------ function getActualScriptVersion() local info = GetInfo(); return 'v' .. info.version; end --------------------------------------------------------------------------------------------------------- -- Initialize - Define the data sources default settings. -- Returns a table of settings. --------------------------------------------------------------------------------------------------------- function Initialize() config = {} config.name = "JSON 2024"; config.initialized = false; config.JSONfile = ''; config.version = getActualScriptVersion(); -- future usage, new.15.Dec.2021, started at 'v4.8.6' return config; end --------------------------------------------------------------------------------------------------------- -- validatemethod --------------------------------------------------------------------------------------------------------- function validatemethod(dialog) local name = dialog:getwidget("Name").value; if name == "" then DIALOG.alert("please enter a valid name."); return "Name"; end local file = dialog:getwidget("edit_file").value; if file == "" then DIALOG.alert("please select a JSON file to process."); return "edit_file"; end return ""; end --------------------------------------------------------------------------------------------------------- -- setDialogWidget --------------------------------------------------------------------------------------------------------- function setDialogWidget(pConfigdialog, pName, pValue) local widget = pConfigdialog:getwidget(pName); widget.content = pValue; pConfigdialog:setwidget(widget); end --------------------------------------------------------------------------------------------------------- -- get_JSON_file_location -- --------------------------------------------------------------------------------------------------------- function get_JSON_file_location() -- ask user for JSON file location local done, path = DIALOG.choosefile("Choose JSON file"); return done, path; end --------------------------------------------------------------------------------------------------------- -- chooseButtonAction --------------------------------------------------------------------------------------------------------- chooseButtonAction = function(configdialog) local done, path = get_JSON_file_location(); -- JSON file location if (done) then actionConfig.JSONfile = path; setDialogWidget(configdialog, "edit_file", actionConfig.JSONfile); end end --------------------------------------------------------------------------------------------------------- -- ConfigureUI -- --------------------------------------------------------------------------------------------------------- function ConfigureUI(config) local enable_name = false; actionConfig = config; if config.initialized == false then enable_name = true; end local title_new = "New JSON 2024 Data Source"; local title_edit = "JSON 2024 Data Source"; local the_title = title_new; if enable_name == false then the_title = title_edit; end configdialog = DIALOG.new( { title = the_title, validate = validatemethod } ); local name_top = 20; local file_top = 20+(25*1); local choose_button_top = 20+(25*2); local button_top = 20+(25*3)+10; local widget_left = 90; local static_right = widget_left; local widget_right = 500; local choose_button_width = 100; local choose_button_left = widget_right - choose_button_width; configdialog:addwidget( { { type = "statictext", title = "Name:", align = "left", left = 20, top = name_top, right = static_right, height = 20 }, { type = "editbox", id = "Name", left = widget_left, top = name_top, right = widget_right, height = 20, content = config.name, enable = enable_name }, { type = "statictext", title = "File:", align = "left", left = 20, top = file_top, right = static_right, height = 20 }, { type = "editbox", id = "edit_file", left = widget_left, top = file_top, right = widget_right, height = 20, content = config.JSONfile, enable = true }, { type = "button", id = "edit_file_choose", title = "Choose", left = choose_button_left, top = choose_button_top, width = choose_button_width, heigth = 20, onchange = chooseButtonAction}, { type = "cancelbutton", title = "Cancel", id = "cancel", left = 270, top = button_top, width = 80, heigth = 20, }, { type = "okbutton", title = "Ok", id = "ok", left = 270+80+20, top = button_top, width = 80, heigth = 20 }, } ); if configdialog:open() then config.name = configdialog:getwidget("Name").content; config.JSONfile = configdialog:getwidget("edit_file").content; return config; end end --------------------------------------------------------------------------------------------------------- -- Synchronize -- config : Configuration parameters (in/out). If changed, will update datasource.xml -- datasource : Data source object -- Returns : new RECORDSET or nil if canceled --------------------------------------------------------------------------------------------------------- function Synchronize(config, datasource) config.initialized = true; return RECORDSET.new(fields_with_options, create_records_from_json(config)); end --------------------------------------------------------------------------------------------------------- -- SaveRecords -- Update changes back to the data source -- config : Configuration parameters (in/out) --------------------------------------------------------------------------------------------------------- function SaveRecords(config, datasource, records) for i=1,records:size() do record = records:getrecord(i); for x=1, record:size() do field = record:field(x); if field:getupdatestate() & 2 == 2 then field:setupdatestate(0); end end end end --------------------------------------------------------------------------------------------------------- -- GetReleaseNotes -- -- This is called when the ‘info’ button is selected associated with a data provider row on the -- Manage Enterprise Data Provider dialog. --------------------------------------------------------------------------------------------------------- function GetReleaseNotes() local body = ""; body = body .. "<h1>JSON 2024 Release Notes</h1>"; body = body .. "<h3>v1.0.0</h3>"; body = body .. "<ul>"; body = body .. "<li>A sample script using JSONPath to parse JSON data</li>"; body = body .. "</ul>"; c = { title = "JSON 2024 Release Notes", body = body, }; return c; end --------------------------------------------------------------------------------------------------------- -- GetInfo --------------------------------------------------------------------------------------------------------- function GetInfo() c = { url = "https://www.65bit.com/docs/creating-custom-json-data-providers/", name = "JSON 2024 File Sample", version = "1.0.0", }; return c; end --------------------------------------------------------------------------------------------------------- -- Given a URI, return true if the download should be handled by this script --------------------------------------------------------------------------------------------------------- function CanResolveAssetURI(field, uri) return false; end --------------------------------------------------------------------------------------------------------- -- Turns a URI into a fully qualified location, from which the storage location is determined --------------------------------------------------------------------------------------------------------- function ResolveAssetURI(config, uri) return uri; end --------------------------------------------------------------------------------------------------------- -- Download the asset to the local cache -- location : result of 'ResolveAssetURI' -- filepath : locale cache full path --------------------------------------------------------------------------------------------------------- function GetAsset(config, location, filepath) return false; end --------------------------------------------------------------------------------------------------------- -- Returns a table of records taken from the JSON with the fields as specified in 'fields_with_options' -- config : Configuration table with file location --------------------------------------------------------------------------------------------------------- function create_records_from_json(config) json = load_file(config.JSONfile); if json == nil or json == "" then error("JSON empty or cannot be loaded"); end records = {} -- Use the records JSONPath to create a table of JSON data table_of_records, err = jsonarraytotable(json, record_JSONPath); if table_of_records == nil then error(err); end for r = 1, #table_of_records do record_json = table_of_records[r]; if record_json ~= "" and record_json ~= nil then r = {} for i = 1, #fields_with_options do r[fields_with_options[i].name] = processjson('jsonpath', record_json, fields_with_options[i].jsonpath); end table.insert(records, r); end end return records; end
The post Creating an Enterprise Data Provider Script For JSON data appeared first on 65bit Software.