jsoneditor/examples/23_custom_query_language.html

124 lines
3.7 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>JSONEditor | Custom query language</title>
<meta charset="utf-8" />
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<script src="https://unpkg.com/lodash@4.17.15/lodash.min.js"></script>
<style type="text/css">
p {
max-width: 500px;
font-family: sans-serif;
font-size: 11pt;
}
code {
font-size: 11pt;
background: #e5e5e5;
}
#jsoneditor {
width: 500px;
height: 500px;
}
.warning {
color: red;
}
</style>
</head>
<body>
<p>
This demo shows how to configure a custom query language.
Click on the "Transform" button and try it out.
</p>
<p>
This basic example uses lodash functions <code>filter</code>, <code>sort</code>, and <code>pick</code>,
but you can run any JavaScript code.
</p>
<p class="warning">
WARNING: this example uses <code>new Function()</code> which can be dangerous when executed with arbitrary code.
Don't use it in production.
</p>
<div id="jsoneditor"></div>
<script>
const container = document.getElementById('jsoneditor')
const options = {
createQuery: function (json, queryOptions) {
console.log('createQuery', queryOptions)
const { filter, sort, projection } = queryOptions
let query = 'data'
if (filter) {
// Note that the comparisons embrace type coercion,
2020-01-04 17:46:21 +08:00
// so a filter value like '5' (text) will match numbers like 5 too.
const getActualValue = filter.field !== '@'
? `item => _.get(item, '${filter.field}')`
: `item => item`
query = `_.filter(${query}, ${getActualValue} ${filter.relation} '${filter.value}')`
}
if (sort) {
// The '@' field name is a special case,
// which means that the field itself is selected.
// For example when we have an array containing numbers.
query = sort.field !== '@'
? `_.orderBy(${query}, '${sort.field}', '${sort.direction}')`
: `_.sortBy(${query}, '${sort.direction}')`
}
if (projection) {
// It is possible to make a util function "pickFlat"
// and use that when building the query to make it more readable.
if (projection.fields.length > 1) {
const fields = projection.fields.map(field => {
const name = _.last(field.split('.'))
return ` '${name}': _.get(item, '${field}')`
})
query = `_.map(${query}, item => ({\n${fields.join(',\n')}})\n)`
} else {
const field = projection.fields[0]
query = `_.map(${query}, item => _.get(item, '${field}'))`
}
}
return query
},
executeQuery: function (json, query) {
console.log('executeQuery', query)
// WARNING: Using new Function() with arbitrary input can be dangerous! Be careful.
const execute = new Function('data', 'return ' + query)
return execute(json)
},
queryDescription: 'Enter a JavaScript query to filter, sort, or transform the JSON data.<br/>' +
'The <a href="https://lodash.com/" target="_blank">Lodash</a> library is available via <code>_</code> to facilitate this.'
}
const json = []
for (let i = 0; i < 100; i++) {
var longitude = 4 + i / 100
var latitude = 51 + i / 100
json.push({
name: 'Item ' + i,
id: String(i),
index: i,
time: new Date().toISOString(),
location: {
latitude: longitude,
longitude: latitude,
coordinates: [longitude, latitude]
},
random: Math.random()
})
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>