====== JSON Data Definition Demo ====== Here are some external files with recipes as JSON data: * [[recipe_butter_cookie]] - pure JSON file. * [[recipe_sweet_sauces]] - DokuWiki page with two JSON data objects inside %%%% tags. ===== JSON from single source ===== ==== Inline ==== { "name": "Butter cookie", "type": "cookie", "Ingredients": { "eggs": "3", "flour": "500 g", "sugar": "300 g", "butter": "250 g" } } { "name": "Butter cookie", "type": "cookie", "Ingredients": { "eggs": "3", "flour": "500 g", "sugar": "300 g", "butter": "250 g" } } ==== External JSON file ==== In this case we have pure JSON external file [[recipe_butter_cookie]]. 'src' may be internal or external [[wiki:syntax#links|DokuWiki link]]. ==== External JSON file from internet ==== Load JSON file from internet into our database (this may not work - depends on server settings): ==== External Dokuwiki page ==== Load JSON data from external DokuWiki page ([[recipe_sweet_sauces]]) with multiple %%%% elements inside. ==== External Dokuwiki page - specific element ==== Specific %%%% element inside the page can be addressed with ''#'' symbol. It corresponds to the id attribute of the remote %%%% element. ==== External file from query string ==== 'src_ext' attribute contains a name of the argument. Argument must be passed with the [[wp>Query string]] added to the link to this page. Recipe in query_string is currently for %$query_string.name%. If 'query_string.name' is not defined and there is tag with Errors, click on it. It says, that 'query srting for json_recipe not defined'. This page should be loaded from link, which includes query string, like this: [[json_definition_demo?json_recipe=recipe_butter_cookie|JSON Data Definition Demo - Butter Cookie]] Click this: [[json_definition_demo?json_recipe=recipe_butter_cookie#external_file_from_query_string|JSON Data Definition Demo - Butter Cookie]] Now the page should reload with data as defined in the link. No Errors should show. Any link can be used in the Query string. Key must be prepended with 'json_'. Multiple key=value combinations may be in the Query string, separated by ''&''. It is possible to address specific %%%% element in query string. However, ''#'' has special meaning in [[wp>URL]] and this sign can not be used as value of the argument. ''%23'' must be used instead. For example, reload this page with data from %%%% element from 'recipe_sweet_sauces' and jump to this chapter (see title of current chapter): [[json_definition_demo?json_recipe=recipe_sweet_sauces%23ganache#external_file_from_query_string|JSON Data Definition Demo - Ganache]] Click this: [[json_definition_demo?json_recipe=recipe_sweet_sauces%23ganache#external_file_from_query_string|JSON Data Definition Demo - Ganache]] ==== Errors ==== If there are errors, they are displayed in 'Errors' tab. For example, missing external file or wrong attributes and JSON syntax: abc abc ===== Combine JSON data from multiple sources ===== In the background, there is a JSON array, which is empty on the beginning, when DokuWiki page starts loading. Then each %%%% element on the page loads some data. If data are loaded to the same 'path', then they are combined, replaced or added somehow. Below are the rules with examples. ==== Replace or add to existing data ==== { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } As you can see, data from the second %%%% are added to the data from the first %%%%. If necessary, data from the second %%%% replace data from the first. ("sugar" in the example changes from "300 g" to "350 g") The same is achieved with the combined %%%% element belov: { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } ==== Load data to the specific path ==== With the 'path' attribute you can specify a path, where to load new data. { "sugar": "350 g", "chocolate chips": "100 g" } { "sugar": "350 g", "chocolate chips": "100 g" } ==== Load specific part of data ==== With the 'src_path' attribute you can specify a path on data referenced by 'src'. Only that part of data will be loaded. { "name": "My cookie" } { "name": "My cookie" } ==== Delete existing data ==== Use ''-'' in the beginning of the 'path' attribute do clear previous data and then load new. ''-'' operator simply remove previous data on the path. For example, you can only remove a part of previously defined data with it. { "margarine": "250 g" } { "margarine": "250 g" } Another example: { "eggs": "3", "flour": "500 g", "sugar": "300 g", "margarine": "250 g" } { "eggs": "3", "flour": "500 g", "sugar": "300 g", "margarine": "250 g" } ==== Stack data ==== If you want to push data into the next free element of the array, you can use ''[]'' operator on the end of the 'path' attribute. [[https://cowburn.info/2010/04/30/glob-patterns/|Wildcard]] characters can also be used for the file name: However, data inside two files with recipes does not have the same format, so combined data is probably not what we want. ==== Load data recursively ==== Make again 'Butter Cookie Enhanced', which is based on 'Butter Cookie': { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } { "name": "Butter cookie enhanced", "Ingredients": { "sugar": "350 g", "chocolate chips": "100 g" } } Then we make a "Butter cookie super enhanced", which is based on 'Butter Cookie Enhanced', which is based on 'Butter Cookie': { "name": "Butter cookie super enhanced", "Ingredients": { "caramel": "50 g" } } { "name": "Butter cookie super enhanced", "Ingredients": { "caramel": "50 g" } } It works perfectly. Recursion depth is controlled by configuration setting 'src_recursive'. By default it is limited to 30 levels and it prevents page crash, if someone makes something stupid, like cyclic reference: { "name": "Butter cookie super enhanced", "Ingredients": { "caramel": "50 g" } } { "name": "Butter cookie super enhanced", "Ingredients": { "caramel": "50 g" } } ===== Build inline JSON from existing data ===== Inside inline json we can use ''%%%$ path [( row_filter )]( filter )%%%'' syntax, which will be replaced by data from existing JSON database. First we define database for 'cars' and 'salesmen'. Then use those data for building 'sale' database, as shown below: { "Renault": { "cars": %$cars[(0 == renault)]%, "salesman": %$salesmen.james_s% }, "other": { "cars": %$cars[(2 == black or 2 == red or 2 == white)]%, "salesman": %$salesmen.george_w% } } %$sale#code#% [ ["BMW", 2016, "black"], ["Renault", 2017, "yellow"], ["Renault", 2018, "green"], ["Tesla", 2018, "white"] ] { "james_s": {"name": "James", "surname": "Smith"}, "george_w": {"name": "George", "surname": "Wright", "middle name": "T."} } { "Renault": { "cars": %$cars[(0 == renault)]%, "salesman": %$salesmen.james_s% }, "other": { "cars": %$cars[(2 == black or 2 == red or 2 == white)]%, "salesman": %$salesmen.george_w% } } %$sale#code#% ===== Reuse existing data with 'src' attribute ===== 'src' attribute is not only used for file path, it can also contain JSON data. For example, existing data from JSON database can be "cloned" with 'src' attribute. Only specific parts can then be changed with inline JSON. { "name": "Cloned butter cookie", } { "name": "Cloned butter cookie" }