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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | --------------------------------------------------------------------------------------------------------- -- 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 |