JSON-Filter


Follow
1
Star
1
Details
Releases
Issues
This application is not supported by InterSystems Corporation. Use it at your own risk.

What's new in this version

  • Fix issue with a hardcoded url.

JSON Filter

This is an application for adding a fews helpful features to your rest services :

Some basic features required in most rest services.

Quick start

Include jsonfilter inc file to your REST services class and apply $$$JSFilter(json) macro to a %DynamicObject Or %DynamicArray.

Include jsonfilter

Class Isc.JSONFiltering.Rest.FilteringDemo Extends %CSP.REST
{

Parameter CONTENTTYPE = {..#CONTENTTYPEJSON};

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
    <Route Url="/demoresponse" Method="GET" Call="demoJsonResponse" Cors="true"/>
</Routes>
}

ClassMethod demoJsonResponse() As %DynamicObject
{
    Set json = [{"name":"John", "city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"},{"name":"Alain","city":"Bruges"},{"name":"Aurélien","city":"Mons"}]

    Write $$$JSFilter(json).%ToJSON()
    
    Return $$$OK
}
}

$$$JSFilter(json) macro apply all json filter features automatically.

Property filtering

It's an interesting feature for your client app that need to reduce the bandwith usage.

Property filter is a simple dynamic array which contain the list of properties.
You can use dot as a separator to specify a nested property.

Set json = {"name" : { "first" : "Edith", "last" : "Scott"}, "friends" : [{"name": "Perkins Cruz", "id":"1", "address":[{"city":"London","street":"no value"},{"city":"Roma","street":"no value"}]}]}

Set propertyFilter = ["name.first","friends.name","friends.address.city"]
Set filteredJSON = $$$JSFilterProperty(json,propertyFilter)

Write filteredJSON.%ToJSON()

For testing purpose in an Iris terminal, you can use a classmethod call instead of $$$JSFilterProperty macro.

Set filteredJSON = ##class(Isc.JSONFiltering.Services.FilteringServices).filterJSON(json,propertyFilter) 

We recommand to always use macro in your app. It would be useful if a class is renamed in a further version.

Result

{"name":{"first":"Edith"},"friends":[{"name":"Perkins Cruz","address":[{"city":"London"},{"city":"Roma"}]}]}

Searching

Seach Criteria work with dynamic array parameters following this syntax [["property","value","operator"],["property2","value2","operator2"],...].
It's the same structure of restriction predicate syntax used with %FindDocuments (%DocDB.Database).

Set json = [{"name":"John", "city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"},{"name":"Alain","city":"Bruges"},{"name":"Aurélien","city":"Mons"}]

Set searchCriteria = [["city","Namur","="]]
Set result = $$$JSFilterCriteria(json,searchCriteria)
Write !,result.%ToJSON()

You can use the folowing classmethod instead of $$$JSFilterCriteria for testing purpose :

Set result = ##class(Isc.JSONFiltering.Services.FilteringServices).searchCriteria(json,searchCriteria)

Result

[{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"}]

Sorting

Sort parameter is a dynamic array with two items.
The first item is the "sort by" property and the second item is the order "desc" or "asc".
If the second item is missing, "desc" is selected by default.
The used property to sort can be a nested property, but not a list or a property in a nested list of object.

Set json = [{"name":"John", "city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"},{"name":"Alain","city":"Bruges"},{"name":"Aurélien","city":"Mons"}]

Set sort = ["city","desc"]
Set result = $$$JSFilterSort(json,sort)
Write !,result.%ToJSON()

You can use the folowing classmethod instead of $$$JSFilterSort for testing purpose :

Set result = ##class(Isc.JSONFiltering.Services.FilteringServices).sort(json,sort)

Result

[{"name":"Alain","city":"Bruges"},{"name":"John","city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Aurélien","city":"Mons"},{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"}]

Limit result

Maximum number of records to return.

Set json = [{"name":"John", "city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Lorenzo","city":"Namur"},{"name":"Matteo","city":"Namur"},{"name":"Alessio","city":"Namur"},{"name":"Alain","city":"Bruges"},{"name":"Aurélien","city":"Mons"}]

Set limit = 3
Set result = $$$JSFilterLimit(json,limit)
Write !,result.%ToJSON()

You can use the folowing classmethod instead of $$$JSFilterLimit for testing purpose :

Set result = ##class(Isc.JSONFiltering.Services.FilteringServices).limitResult(json,limit)

Result

[{"name":"John","city":"Charleroi"},{"name":"Tony","city":"Charleroi"},{"name":"Lorenzo","city":"Namur"}]

How it works with REST client app

Client REST app can use these features just by adding request parameters.
See the following tab:

Feature Request Parameter Name Example Value
Property filtering jsflt name,friends[name,address[city]]
Searching jsfltsc ["name.first","Edith","="]
Sorting jsfltsrt name.first,desc
Limit jsfltlmt 5

There is no mandatory query parameter.

Back-end REST app

Backend application retrieve filter data provided by client app and process it with $$$JSFilter macro.
In the following example, the macro return a filtered %DynamicObject or %DynamicArray.
json is a %DynamicObject or %DynamicArray to filter.

Set filteredJSON = $$$JSFilter(json)

The macro $$$JSFilter retrieve all filters data in %request.Data and call the appropriate process.

Available macro :

Feature Macro Classmethod
Property filtering $$$JSFilterProperty(json,propertyFilter) ##class(Isc.JSONFiltering.Services.FilteringServices).filterJSON
Searching $$$JSFilterCriteria(json,searchCriteria) ##class(Isc.JSONFiltering.Services.FilteringServices).searchCriteria
Sorting $$$JSFilterSort(json,sort) ##class(Isc.JSONFiltering.Services.FilteringServices).sort
Limit $$$JSFilterLimit(json,limit) ##class(Isc.JSONFiltering.Services.FilteringServices).limitResult
All By %Request $$$JSFilter(json) ##class(Isc.JSONFiltering.Services.FilteringServices).applyAllFilterParameters

Remember to use macros in your app instead of classmethod.

Prerequisites

Make sure you have git and Docker desktop installed.

Installation

Clone/git pull the repo into any local directory

$ git clone https://github.com/lscalese/isc-rest-json-filter.git

Open the terminal in this directory and run:

$ docker-compose build
  1. Run the IRIS container with your project:
$ docker-compose up -d

Installation from ZPM client

Open an Iris Terminal

zpm
install json-filter
install swagger-ui

How to Test it

Unit Test

Not available with zpm install.

Open IRIS terminal:

$ docker-compose exec iris irissession iris
USER>zn "IRISAPP"
IRISAPP>Set ^UnitTestRoot = "/opt/irisapp/tests/"
IRISAPP>Do ##class(%UnitTest.Manager).RunTest(,"/nodelete")

Swagger-UI

There is Open API Specification 2.0.
Swagger-UI can be used:

  • Go to this page http://localhost:52773/swagger-ui/index.html
  • put http://localhost:52773/csp/jsonfilterrest/_spec in search bar
  • click explore

swagger-ui

Test page

Basic test page : http://localhost:52773/csp/jsonfilter/Isc.JSONFiltering.Rest.FilteringCSPDemo.cls

test_page_capture

This page is now useless with swagger-ui module.

Postman collection

For testing purpose a Postman collection is available with some filter examples.

License

This project is licensed under the MIT License - see the LICENSE file for details.

How to start coding

This repository is ready to code in VSCode with ObjectScript plugin. Install VSCode, Docker and ObjectScript plugin and open the folder in VSCode. Open /src/cls/PackageSample/ObjectScript.cls class and try to make changes - it will be compiled in running IRIS docker container. docker_compose

Feel free to delete PackageSample folder and place your ObjectScript classes in a form /src/Package/Classname.cls Read more about folder setup for InterSystems ObjectScript

The script in Installer.cls will import everything you place under /src into IRIS.

What's inside the repository

Dockerfile

The simplest dockerfile which starts IRIS and imports Installer.cls and then runs the Installer.setup method, which creates IRISAPP Namespace and imports ObjectScript code from /src folder into it. Use the related docker-compose.yml to easily setup additional parametes like port number and where you map keys and host folders. Use .env/ file to adjust the dockerfile being used in docker-compose.

.vscode/settings.json

Settings file to let you immedietly code in VSCode with VSCode ObjectScript plugin)

.vscode/launch.json

Config file if you want to debug with VSCode ObjectScript

Read about all the files in this artilce

Links

If you are interested by these features, you will be probably interested by GraphQL approach.
An Objectscript implementation by Gevorg Arutiunian is available here.

ZPM installation
zpm "install json-filter"
Category
Developer Environment
Works with
InterSystems IRIS
Tags
Info
Version
1.4.4
Last updated
2020-05-02
Repository
Open
Documentation
Open
License
Link