How to solve jsonLogic, GraphQL Unsupported Query Keys using Lodash
When it comes to data structure for storing or transferring a set of rules that should be defined from the client, jsonLogic its a great choice.
“Build complex rules, serialize them as JSON, share them between front-end and back-end” is how the home page for JsonLogic starts describing the library.
The client can define rules in Json format that can be used in many systems to perform validations.
The Problem:
When you want to save the jsonLogic rules (as JSON) using GraphQL the jsonLogic’s operators ==
, ===
, !=
, !==
, >
, >=
, <
, <=
, !!
, !
, %
, +
, *
, -
, and /
are not supported from GraphQL as Query Keys
The Solution:
json-logic-js-graphql to rescue!
json-logic-js-graphql it is using json-logic-js as a dependency and adds on top a few useful immutable helpful functions from Lodash without changing the default functionality
Installation:
# Yarn
$ yarn add json-logic-js-graphql# NPM
$ npm install json-logic-js-graphql --save
Using a GraphQL Mutation:
We will send a mutation from the client (GraphQL playground) to GraphQL server and then save the rule input as json in the database.
The Input:
The rules should be saved as a Json
in the db and the GraphQL input type should be an Json
input type.
1. Database: If we are using MongoDB and mongoose the Schema should be a “anything goes” Mixed SchemaType
and will look like this:
import mongoose from 'mongoose';
const { Schema } = mongoose;const ruleSchema = new Schema({
title: { type: String, required: true },
condition: { type: Schema.Types.Mixed, required: true },
});
2. GraphQL input: The field it is anJSONObject
using graphql-scalars
input RuleInput {
title: String
condition: JSONObject
}
The GraphQL Query:
Use any of _eq
, _gt
, _gte
, _lt
, _lte
etc from Lodash methods.
The condition
it is the actual Json rule, we will use to validate our data,
Replace the ===
with the _eq
method.
mutation {
updateRule(
id: "609ce9dbec9fb60004087784"
condition: { _eq: [{ var: "foo" }, "bar"] }
) {
id
}
}
json-logic-js-graphql
supports around 248 Lodash methods
All Lodash methods exposed with the
_
namespace to avoid overwriting the default jsonLogic's functionality
Using Javascript:
import { jsonLogic } from 'json-logic-js-graphql'const rules = {
_eq: [{ var: 'foo' }, { var: 'bar' }],
}
const data = { foo: 'bar', bar: 'bar' }jsonLogic.apply(rules, data)
How it works:
key: You can use the docs https://lodash.com/docs to locate the methods you want to use, add the _
as a prefix and this is the rule key.
value: The value it is the method’s parameters as an array. The order of the array matters because this is how jsonLogic use the order to call the method with the params!
The key its the method and value an array of the params
Example:
For example we want to use the chunk method
The chunk
usage is:
_.chunk(array, size)
So the first argument its the array and the second the size
_.chunk(['a', 'b', 'c', 'd'], 2);
In json-logic-js-graphql
will be:
{_chunk: [["a","b","c","d"], 2]}
So the results is:
[["a","b"],["c","d"]]
Extras: Date functions using momentJs:
The json-logic-js-graphql also supports a few useful date comparison methods like:
_gteDate
, _gtDate
, _lteDate
, _ltDate
, _eqDate
, _getDate
Example:
const rules = {
_gteDate: [
[{ var: 'from' }, { var: 'to' }],
[364, 'days'],
],
}
const data = { from: '2020-10-01', to: '2021-10-01' }jsonLogic.apply(rules, data)
Expect: from..to >= 364 days
Conclusion:
Exposing Lodash methods to jsonLogic we can manipulate data with more flexibility also support GraphQL Query Keys