I have a JOI validation scheme which some values which I need in some other scheme's and other places too, so I placed all those values in a seperated file and import them in the scheme.
Scheme:
const ENUMS = require(path.join(__dirname, 'enums'))
const Product = Joi.object({
name: Joi.string(),
category: Joi.string().valid(ENUMS.validProductCategory),
description: Joi.string().allow(ENUMS.empty)
})
Enums.js
module.exports.productCategory = ['JEWEL', 'WATCH', 'EARRING']
module.exports.empty = '', null
The problem is that Joi.valid() and Joi.allow() does not accept arrays as values (see https://joi.dev/api/?v=17.5.0#anyallowvalues). The values in the function needs to passed as .valid('a', 'b')
I don't know how the let that values return from the enums file. I have tried some ways (like the module.exports.empty) and with the spreading (...) options.
I don't get it to work either, so I'm wondering how I can return the string in the right format to reuse it?
if you have an enum e.g
enum ValidStringsEnum {
DESCRIPTION_ONE = "description one",
DESCRIPTION_TWO = "description two",
}
you could do:
description: Joi.string().valid(...Object.values(ValidStringsEnum))
Related
i just know that the object Json can be an XMl file by the js2xml library,
so that's why I'm trying to convert the following json to XML,
How can I achieve this in NodeJS?
i can't find an answer or a documentation that can help me?
here is the model JSON
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: [true, "Please provide email address"],
unique: true,
match: [
/^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]
{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
"Please provide a valid email",
],
},
password: {
type: String,
required: [true, "Please add a password"],
minlength: 6,
select: false,
},
const User = mongoose.model("User", UserSchema);
module.exports = User;
i used this exemple that didn't work for me
function groupChildren(obj) {
for(prop in obj) {
if (typeof obj[prop] === 'object') {
groupChildren(obj[prop]);
} else {
obj['$'] = obj['$'] || {};
obj['$'][prop] = obj[prop];
delete obj[prop];
}
}
return obj;
}
const xml2js = require('xml2js');
const obj = {
Level1: {
attribute: 'value',
Level2: {
attribute1: '05/29/2020',
attribute2: '10',
attribute3: 'Pizza'
}
}
};
const builder = new xml2js.Builder();
const xml = builder.buildObject(groupChildren(obj));
console.log(xml);
When converting JSON to XML, one has to ask: what XML do you want to convert it to? Does it have to be a specific XML format, or will any old XML do?
If any old XML will do, then you can usually find some library to do the job, such as js2xml or js2xmlparser. The problem with these libraries is that they usually offer very little control over how the XML is generated, especially for example if there are JSON objects with keys that are not valid XML names (which doesn't apply in your case).
If you want a specific XML format then I would recommend using XSLT 3.0, which is available on node.js in the form of Saxon-JS. [Disclaimer: my company's product]. If you are interested in pursuing this approach, then tell us what you want the output to look like, and we can help you create it.
There are many different packages for XML serialization.
Most of them enforce a specific XML and JSON mapping convention.
Others require you to build the XML document in code.
Finally, there are solutions that do this with decorators. Those give you freedom in defining the structure without having to build the document entirely in code.
As an example: the xml decorators package.
It means that you define the XML mapping using a class. Next, you define decorators on top of each field, to define how it should be mapped to XML.
import { XMLAttribute, xml } from 'xml-decorators';
const NS = 'ns';
export class User {
#XMLAttribute({namespace: NS})
private email:string;
#XMLAttribute({namespace: NS})
private password: string;
constructor(email: string, password: string) {
this.email = email;
this.password = password;
}
}
And finally, to actually serialize
const user = new User('foo#bar.com', 'secret');
const xml = xml.serialize(user);
Conceptually, this is certainly a robust solution, since it strongly resembles how java xml binding (JAXB) and C# xml serialization work.
I am trying to use the "or" operator in Joi ver.17.4.0
As you can see, in the code below, I want either or both of the attributes/properties to be allowed, but not neither.
The problem is that Joi does not allow a string to be empty. So, to have it empty, I need to:
Joi.string().allow('')
This makes it not empty according to the "or" operator. So I can not get the 'name' to be empty in the eyes of "or".
It won't validate properly.
It validates even when I do this (but it shouldn't):
validatePerson(createPerson(''));
Keep in mind that I'm actually validating POST input on a node express API, so this is some simplified code to illustrate the issue:
const Joi = require('Joi');
function createPerson(name, age) {
const person = { name: name, age: age };
console.log(person);
return person;
}
function validatePerson(person) {
const schema = Joi.object({
name: Joi.string().allow(''),
age: Joi.number(),
}).or("name", "age");
console.log(schema.validate(person));
return schema.validate(person);
}
validatePerson(createPerson('')); // This should fail validation but doesn't
validatePerson(createPerson()); // Should fail and does
validatePerson(createPerson('Bob')); // Should pass and does
validatePerson(createPerson('', 7)); // Should pass and does
validatePerson(createPerson('Bob', 7)); // Should pass and does
As far as I understand, you want to allow the name to be empty an string, only if the age exists.
To acheive that, you can use .when:
name: Joi.string().when('age', { is: Joi.exist(), then: Joi.allow('') })
This way, your first example will fail as you expected.
This is my Scenario. I want validate same key but different datatypes passing in joi validation. How to achieve this:
joi validate
static validateSearchedProduct(request_query) {
const joiSearchedProductSchema = Joi.object({
product_category: Joi.objectId()
})
return Joi.validate(request_query, joiSearchedProductSchema);
}
function
validateSearchedProduct({product_category:"5d44258bcb9b611da1f658c8"})
validateSearchedProduct({product_category:["5d44258bcb9b611da1f658c8"]})
So, you want product_category to be either string or array of strings. Then, you could use Joi.alternatives and do something like that:
static validateSearchedProduct(request_query) {
const joiSearchedProductSchema = Joi.object({
product_category: Joi.alternatives().try(
Joi.string(),
Joi.array().items(Joi.string())
)
})
return Joi.validate(request_query, joiSearchedProductSchema);
}
And Joi.string() can be replaced with whatever that is needed (e.g. Joi.objectId).
I have a query that returns an array, with Object.key (array) .foreach I am iterating, I want to know the value of a property in specific array.
Example:
Object.keys(arreglo).forEach(function(key) {
console.log(arreglo[key]);
});
The output is:
name: "Pepito",
Surname: "Perez"
I want to know how to get only the value of the surname
I know it will not work but it would be something like:
console.log(arreglo[key].surname);
You can use Array.forEach on the original array as shown below. You can even extract the fields you are interested using Array.map.
// let's assume the arrary you got from your query is in this format
const arreglo = [
{ firstname: "fn1", surname: "ln1"},
{ firstname: "fn2", surname: "ln2"},
{ firstname: "fn3", surname: "ln3"}
];
// you can log `surname` for each entry in the array
arreglo.forEach(v => console.log(v.surname));
// you can use map to transform the array to just have `surname` using array.map()
const surnames = arreglo.map(v => v.surname);
console.log(surnames);
Is this what you are looking for
const object1 = {
a: {firstname:"sali",lastname:"mali"},
b: {firstname:"sali",lastname:"mali"},
c: {firstname:"sali",lastname:"mali"}
};
Object.keys(object1).forEach(function(key){console.log(object1[key].lastname)});
My requirement is to mask certain fields of a JSON while logging them.I am working on node.js. I have used json-masker library of node.js. While passing the JSON path of attributes with "-" in the name in the "whitelist" parameter, I am getting lexical error.
JSON
{
"attribute1":"value1",
"attribute2":"value2",
"attribute-name":"value3"
}
Code
const masker = require('json-masker');
const mask= masker({
whitelist: ['$.attribute1','$.attribute-name']
});
Error
Error Lexical error on line 1. Unrecognized text.
$.attribute-name
Also, is there a way to specify only the attributes that needs to be masked rather that specifying the ones that need not be masked(as specified in whitelist).
Please suggest if there is a better approach to do this using any other function/library.
Please note that I am receiving this JSON , so I cannot change the key name
The correct syntax is '$["attribute-name"]' instead of '$.attribute-name'
The $ fields are processed by jsonpath, a dependency of json-masker. This issue is discussed in one of their github issues (#90) and the solution presented there.
Use maskdata npm module: https://www.npmjs.com/package/maskdata
You can mask json fields containing '-' without any extra effort. Also, you can mask the nested fields too.
Example:
const MaskData = require('./maskdata');
const maskJSONOptions = {
// Character to mask the data. Default value is '*'
maskWith : "*",
// It should be an array
// Field names to mask. Can give multiple fields.
fields : ['level1.level2.level3.field3', 'level1.level2.field2', 'level1.field1', 'value1']
};
const nestedObject = {
level1: {
field1: "field1",
level2: {
field2: "field2",
level3: {
field3: "field3",
}
}
},
value1: "value"
};
const maskedObj = MaskData.maskJSONFields(nestedObject, defaultJSONMaskOptions2);
//Output : {"level1":{"field1":"******","level2":{"field2":"******","level3":{"field3":"******"}}},"value1":"*****"}