NodeJS validation library for json objects - json

I need to validate some object in my NodeJS app. I have already used an awesome library express-validator, it works perfectly, but now I need to validate different object, not only requests and as far as express validator leverages validator library, that in turn doesn't support types other than the string type.
I have found different variants like Jsonschema, Ajv
They offer great features, but I need to be able to set error message and than just catch an exception or parse it from return object.
Like that
var schema = {
"id": "/SimplePerson",
"type": "object",
"properties": {
"name": {"type": "string", "error": "A name should be provided"},
"address": {"$ref": "/SimpleAddress"},
"votes": {"type": "integer", "minimum": 1}
}
};
So I can set an error message for every property.
Is there any existing solution to achieve this functionality ?
POSSIBLE SOLUTION
I have found a great library JSEN It provides necessary features.

Three powerful and popular libraries you can use for JSON validation are
AJV: https://github.com/epoberezkin/ajv
JOI: https://github.com/hapijs/joi
JSON validator: https://github.com/tdegrunt/jsonschema
All of these libraries allow you to validate different data types, do conditional validation, as well as set custom error messages.

One solution is to use Joi library :
https://github.com/hapijs/joi
This library is well maintained, used and offer lots of flexibility and possible actions.
Example :
const Joi = require('joi');
const schema = Joi.object().keys({
name: Joi.string().error(new Error('A name should be provided')),
address: Joi.ref('$SimpleAddress'),
votes: Joi.number().min(1),
});
// Return result.
const result = Joi.validate(yourObject, schema);

I use Json Pattern Validator
npm install jpv --save
usage
const jpv = require('jpv');
// your json object
var json = {
status: "OK",
id: 123,
type: {}
}
// validation pattern
var pattern = {
status: /OK/i,
id: '(number)',
type: '(object)'
};
var result = jpv.validate( json , pattern)

You can also try nonvalid, a library that supports callback-based validation with custom checks and errors (disclaimer: it is written by me).

I'm about to embark on validation of JSON submissions to my web service and will be using tcomb-validation. It's a lightweight alternative to JSON schema and is based on type combinators.
Example of 'intersections':
var t = require('tcomb-validation');
var Min = t.refinement(t.String, function (s) { return s.length > 2; }, 'Min');
var Max = t.refinement(t.String, function (s) { return s.length < 5; }, 'Max');
var MinMax = t.intersection([Min, Max], 'MinMax');
MinMax.is('abc'); // => true
MinMax.is('a'); // => false
MinMax.is('abcde'); // => false

Related

Monaco editor default json uri schema

I'm using monaco editor to edit JSON and I would like to set a custom diagnostic option.
I'm trying that https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-json-defaults
// Configures two JSON schemas, with references.
var jsonCode = [
'{',
' "p1": "v3",',
' "p2": false',
"}"
].join('\n');
var modelUri = monaco.Uri.parse("a://b/foo.json"); // a made up unique URI for our model
var model = monaco.editor.createModel(jsonCode, "json", modelUri);
// configure the JSON language support with schemas and schema associations
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
schemas: [{
uri: "http://myserver/foo-schema.json", // id of the first schema
fileMatch: [modelUri.toString()], // associate with our model
schema: {
type: "object",
properties: {
p1: {
enum: ["v1", "v2"]
},
p2: {
$ref: "http://myserver/bar-schema.json" // reference the second schema
}
}
}
}, {
uri: "http://myserver/bar-schema.json", // id of the second schema
schema: {
type: "object",
properties: {
q1: {
enum: ["x1", "x2"]
}
}
}
}]
});
monaco.editor.create(document.getElementById("container"), {
model: model
});
Where does uri: "http://myserver/foo-schema.json" come from ? I just want to use default JSON schema. Not my own.
Setting uri like this works :
uri: "http://localhost:4200/assets/monaco-editor/min/vs/language/json/jsonMode.js",
But is there a clean way to set this value ? Maybe uri value for JSON is available somewhere ? I searched through monaco.languages.json.jsonDefaults but I did not find anything.
"http://myserver/foo-schema.json" is an arbitrary value-- you can make it anything you want. It only matters if you are also using enableSchemaRequest-- in which case it should point to the location that you want the schema to be fetched from-- but you're not doing that, so that doesn't matter. In fact, everything related to this URI is irrelevant to what you are trying to do, if I'm understanding your intent correctly.
When you say "I just want to use default JSON Schema, Not my own", I think what you mean to say is that you just want to ensure that it is valid JSON, right? Because, there is no such thing as "default JSON Schema"-- by definition, it is defined by you-- but there is such a thing as a formal definition of what JSON is (JSON Schema, on the other hand, assumes that you are already starting with valid JSON, and allows you to then define a schema that your (valid) JSON must conform to).
Assuming you just want to ensure it is valid JSON (but you don't care that the json conform to some custom schema), setting the language to 'json' is all you need to do and your code can be as simple as:
var myBadJSONText = '{this is not : "JSON"}'
monaco.editor.create(document.getElementById('container'), {
language: 'json',
value: myBadJSONText
});
which running in the Monaco playground gives you:

What's the best way to map objects into ember model from REST Web API?

The topic of this post is: my solution is too slow for a large query return.
I have a Web Api serving REST results like below from a call to localhost:9090/api/invetories?id=1:
[
{
"inventory_id": "1",
"film_id": "1",
"store_id": "1",
"last_update": "2/15/2006 5:09:17 AM"
},
{
"inventory_id": "2",
"film_id": "1",
"store_id": "1",
"last_update": "2/15/2006 5:09:17 AM"
}
]
Since my WebAPI did not provide a root key for my JSON response, I made a RESTSerializer like following.
export default DS.RESTSerializer.extend({
extract:function(store,primaryType,payload,id,requestType){
var typeName = primaryType.typeKey;
var data = {};
data[typeName] = payload; // creating root
payload = data;
return this._super(store,primaryType,payload,id,requestType)
}
});
When this gets run, I get the following error message: Assetion failed: You must include an 'id' for inventory in an object passed to 'push'
As you can see, these objects do not have the attribute id, so I found that the default behaviour of Ember RESTSerializer forces me to write my own.
Okay, so here's where I'm not sure my solution is right. inventory_id from my return is unique, therefore I choose to use that as an id, okay I'm thinking to my self, I'll just add it manually. The function looks like this now:
export default DS.RESTSerializer.extend({
extract:function(store,primaryType,payload,id,requestType){
var typeName = primaryType.typeKey;
for(var i=0;i<payload.length;i++){
payload[i].id = payload[i].inventoryId;
}
var data = {};
data[typeName] = payload; // creating root
payload = data;
return this._super(store,primaryType,payload,id,requestType)
}
});
By just manually duplicating an attribute, I feel like I'm cheating my way over this error message. In addition, I sometimes return a large payload array (over 150k rows). Looping O(n) just doesn't seem a right price to pay for just a simple mapping.
Is there some other way to set either my WebAPI or serializer up so I avoid the for loop in assigning the id that ember so desperately wants.
I think this should fix your problem:
export default DS.RESTSerializer.extend({
primaryKey: 'inventory_id'
});
With this parameter Ember Data will map inventory_id to it's id parameter.

Can I store a node process variable in JSON?

I am currently in the process of migrating an Express app to Heroku.
To keep sensitive information out of source, Heroku uses config vars which are assigned by to process variables of the same name.
Currently, I am loading my keys using .json, such as:
{
"key": "thisismykey",
"secret": "thisismysecret"
}
However, if I try to load the variables in via Heroku's format:
{
"key": process.env.KEY
"secret": process.env.SECRET
}
Obviously, I get an error here. I would assume that it is possible to load these values into JSON, but I'm not sure. How could I do this?
To generate JSON with these values, you would first create a JavaScript object and then use JSON.stringify to turn it into JSON:
var obj = { "key": process.env.KEY
"secret": process.env.SECRET };
var json = JSON.stringify(obj);
// => '{"key":"ABCDEFGH...","secret":"MNOPQRST..."}'

Sending complex JSON with fetch, save, and delete on a model or collection

We have an internal API that was specifically built to be used with a new piece of software I'm building that runs on Backbone. The API has a single URL and takes JSON as input to determine what it needs to return. It essentially allows me to build custom queries with JSON that return exactly what I'm looking for.
Thing is this JSON can get pretty verbose and is often 3–4 levels deep, but sometimes may just be a few lines and just 1 level deep.
First question first: How do I send a string of JSON along with the ID when I do a fetch()? Do I have to set these parameters as the model or collection's defaults?
Here is an example of a really simple string to get a specific user's info
{
"which" : "object",
"object" : {
"type" : "customer",
"place" : "store",
"customerID" : "14"
}
}
As others have suggested it will likely be challenging to work with SOAP, but it shouldn't be impossible. Backbone models and collections communicate with the server through the sync operation; you should be able to customize that. I think something along these lines might get the ball rolling (for models):
Backbone.SoapyModel = Backbone.Model.extend({
sync: function(method, model, options) {
// force POST for all SOAP calls
method = 'create';
options = _.extend(options, {
// Setting the data property will send the model's state
// to the server. Add whatever complexity is needed here:
data: JSON.stringify({
"which" : "object",
"object" : model.toJSON()
}),
// Set the request's content type
contentType: 'application/json'
});
// Defer the rest to Backbone
return Backbone.sync.apply(this, [method, model, options]);
}
});
var SoapyModelImpl = Backbone.SoapyModel.extend({
url: '/test'
});
var soapTest = new SoapyModelImpl({
id: 42,
name: 'bob',
address: '12345 W Street Dr',
phone: '867 5304'
});
soapTest.fetch();

working with JSON data, trying to parse nested data

I just working with JSON data and am playing around with jQuery and Ajax requests. Pretty basic stuff, but here's my problem.
I have a basic data set which I was using for time tracking. I know how to parse the simple JSON data like this:
{
"end" : "1/18/2011",
"start" : "1/18/2011",
"task" : "Code Review",
},
It's the more complicated stuff I'm trying to parse like this where I'm trying to pull the "time" data out.
{
"end" : "1/17/2011",
"start" : "1/17/2011",
"task" : "Exclusive Brands",
"time" : {
"analysis" : 4,
"documentation" : 3,
"meetings" : 2
}
This is the code for the script I've been using to parse the simple data:
$(function() {
$('.load').click(function(){
$.getJSON("data.js",function(data){
$.each(data.timesheet, function(i,data){
var div_data ="<div class='box'>"+data.start+" "+data.task+"</div>";
$(div_data).appendTo("#time-tracking");
});
}
);
return false;
});
});
My question is what's the format to parse the time data, or what's the best way to parse the information nested inside the time element?
Any help will be greatly appreciated.
A JSON string will be parsed into an object. When parsed, the time is the key of one object. You could retrieve the value of this object through the dot operator (.).
data = JSON.parse('{"end":"1/17/2011", "start":"1/17/2011", "task":"Exclusive Brands", "time": {"analysis":4, "documentation":3, "meetings":2 } }')
// => obj
data.time.analysis
// => 4
In your case similarly you could use the data.time.meetings to access your data from remote server.
Unless I am terribly mistaken, since jquery already converted data into a javascript for you, you should be able to access time as if it was a javascript object like so:
var analysis = data.time.analysis;
var documentation = data.time.documentation;
var meetings = data.time.meetings;
etc...