How to validate object constraint in a object using joi? - javascript

I am trying object validation with the help of joi.
I want to validate object as a constraint inside an object like
let login = {
value: 0/1,
slots: [{ label: '', value: '24 hr'}, { label: '', value: '24 hr'}]
}
Here login is an object and inside it slots is also an object. So if I write like the following
const schema = Joi.object().keys({
value : Joi.number.required(),
slots : Joi.string.required()
});
would it be correct for object data type or should I replace string data type with object data type?
I want to validate object type as a constraint.

Your slots key needs to be an array of objects:
const schema = Joi.object().keys({
value: Joi.number().required(),
slots: Joi.array().items(
Joi.object().keys({
label: Joi.string().required().allow(''),
value: Joi.string().required()
})
)
})
This way, the following object will be valid:
const obj = {
value: 1,
slots: [
{
label: '',
value: '24 hr'
}
]
}

Related

Vue JS lodash findKey nested object with dot notation returns undefined

I'm trying to pull out a value for a nested object key from some eligibility array that I've got, but I'm getting an undefined value for some reason and need to know what I'm missing.
Given the following array:
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
{ field: 'applicant.birthday', operator: '>=', value: 40 },
{ field: 'applicant.isHomeowner', operator: '==', value: false }
]
I need to find loan.amount from a nested object and pull out it's value:
My big nested object is (coming from the store)
application: {
meta: {
brand: '',
version: '',
affiliate: '',
affiliate_full: '',
campaign: '',
client_hostname: '',
client_href: '',
client_origin: '',
client_useragent: '',
client_ip: '127.0.0.1',
icicle_hash: ''
},
loan: {
amount: 500,
term: null,
purpose: null
}
}
My function right now is:
checkEligibility () {
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
{ field: 'applicant.birthday', operator: '>=', value: 40 },
{ field: 'applicant.isHomeowner', operator: '==', value: false }
]
for (const [index, offer] of this.datasets.offers.entries()) {
const eligibility = eligibilityCriteria
if (eligibility) {
for (const [ci, criteria] of eligibility.entries()) {
// TODO: this fails to pull the value, returns undefined
const field = _.findKey(this.$store.state.application.application, criteria.field)
}
}
}
}
What am I missing?
You must have to misunderstood what _.findKey() does
This method is like _.find except that it returns the key of the first element predicate returns truthy for instead of the element itself.
See Example 2 in the code below.
If you want to retrieve the value from the object at a given path, you must use _.property() (Example 2 below)
const eligibilityCriteria = [
{ field: 'loan.amount', operator: '>=', value: 1000 },
{ field: 'loan.term', operator: '>=', value: 1 },
]
const application = {
loan: {
amount: 500,
term: 2,
amount2: 0,
}
}
// example 1
// outputs "loan"
console.log(_.findKey(application, "amount"))
// outputs undefined - there is no key in application object that has property chain "loan.amount"
console.log(_.findKey(application, "loan.amount"))
// outputs undefined - "amount2" key is there but the value is falsy
console.log(_.findKey(application, "amount2"))
// example 2
for (const [ci, criteria] of eligibilityCriteria.entries()) {
console.log(criteria.field, _.property(criteria.field)(application))
}
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.21/lodash.min.js"></script>

JSON schema - new sub schema based on a property

I wanted a JSON schema that could have 3 fields: num, key1, and key2. Both num and key1 are mandatory fields. The field key2 is mandatory ONLY WHEN the key1 was provided a value of 'abc'. Here is the schema that I have created:
schema = {
type: 'object',
additionalProperties: false,
properties: {
num: {
type: 'number',
minimum: 1,
maximum: 5
},
key1: {
type: 'string',
enum: ['abc', 'def']
}
},
required: ['num', 'key1'],
if: {
properties: {
key1: {
const: 'abc'
}
}
},
then: {
properties: {
key2: {
type: 'string',
required: true
}
}
}
};
Here is the instance that I want to validate against the schema using npm module jsonscehma ("jsonschema": "^1.2.0"):
instance = {
num: 1,
key1: 'abc'
};
var Validator = require('jsonschema').Validator;
var v = new Validator();
console.log(v.validate(instance, schema));
My expectation here is that, since the value of key1 is 'abc', this should ideally throw an error saying
mandatory field "key2" is missing
But, there is no such error in this case.
Also, if I provide key2 in the instance, I am getting
additionalProperty "key2" exists in instance when not allowed
even though, key1 is 'abc'.
Please specify if I have missed anything here.
The library you're using only supports draft-04 of the specification.
if / then / else wasn't added till draft-07.

Make a new object from an array of objects [duplicate]

This question already has answers here:
Create an object with dynamic property names [duplicate]
(2 answers)
Closed 6 years ago.
This is possibly a duplicate, but everywhere I search I can only seem to find people wanting to create an array of objects.
Basically I'm trying to achieve the opposite, pull certain values of an array of objects out into an object. It's twisting my head a little so any of you JS gurus out there if you could give me a hand it would be very very appreciated!
Basically I have an array of objects like this:
[
{ field: 'name', value: 'sam', isRequired: true },
{ field: 'email', value: 'sam#dummyemail.net', isRequired: true },
{ field: 'message', value: 'hey', isRequired: false },
]
They're split up this way because I go through the fields for validation.
After the validation phase I want to map the field and value properties to name value pairs within a new object e.g:
{
name: 'sam',
email: 'sam#dummyemail.net',
message: 'hey',
}
Like I said any help would be amazing! Cheers.
Array#map each object in the array into a new object with field as the key of a property, and value, well, the value of the property. Then combine the new objects array to object using the spread syntax and Object#assign:
const arr = [
{ field: 'name', value: 'sam', isRequired: true },
{ field: 'email', value: 'sam#dummyemail.net', isRequired: true },
{ field: 'message', value: 'hey', isRequired: false },
];
const result = Object.assign({}, ...arr.map(({ field, value }) => ({ [field]: value })));
console.log(result);
you could map array into object like this
var array = [
{ field: 'name', value: 'sam', isRequired: true },
{ field: 'email', value: 'sam#dummyemail.net', isRequired: true },
{ field: 'message', value: 'hey', isRequired: false },
];
var object = {};
array.forEach(x => {
object[x.field] = x.value;
});
console.log(object);

How to create field using variable name?

How can I create a field in mongoose using a variable name? I've seen some ways to do it using .update(), but I was wondering if there was a way to do it when creating a new document
I have my schema like:
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
})
and my object:
var date = '2015-02-01'
var obj = {
ios: 100,
android: 500
}
var doc = {}
doc[date] = obj
var mongoDoc = new Summaries({
name: 'John',
type: 'person',
date: date,
$doc: doc
})
mongoDoc.save(function(err){
if(!err) log('done')
else log(err.toString())
})
But it only saves the fields 'name', 'type' and 'date'.
Can anyone tell me if its possible to do something like that and if so, what am I missing?
Got it..
first part from #Alex is right, just change the schema strict property to false so I can add new fields to my mongo document. For the field name as a variable, I just first created my entire object and then create a new instance of the document:
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
}, { strict: false })
var date = '2015-02-01'
var obj = {
name: 'John',
type: 'person',
date: date
}
obj[date] = {
ios: 100,
android: 500
}
var mongoDoc = new Summaries(obj)
mongoDoc.save(function(err){
if(!err) log('Done.')
else log(err)
}
Success!
EDIT
Three years later ES6 syntax also allows us to do so:
var mongoDoc = await new Summaries({
name: 'John',
type: 'person',
date: date,
[date]: { ios: 100, android: 100 }
}).save();
Change your schema definition to
var summariesSchema = mongoose.Schema({
type: String,
name: String,
date: String
}, { strict: false })

need javascript array format

I am looking to create following format in array in javascript.
Each item has:
url -> string (which is login URL)
name -> string
inputs -> array
And each input is:
name -> string
type -> string
value -> string
Please guide me , how to do this in JavaScript
[
{url: 'http://google.com/',
name: 'google',
inputs: [
{ name: 'search-term', type: 'string', value: 'javascript' },
{ name: 'region', type: 'country-code', value: 'IN' }
]
},
{url: 'http://yahoo.com/',
name: 'yahoo',
inputs: [
{ name: 'search-term', type: 'string', value: 'javascript' },
{ name: 'region', type: 'country-code', value: 'US' }
]
}
]
there you go.
on a related note, JSON might be worth looking at once. Though I must say, the above is not json, only json-like.
This would be tricky in a strongly typed language like Java or C#, but it's pretty easy in JavaScript.
Since JavaScript doesn't have strong typing for array values and variables, you can just create an array of object literals. Each object would contain the properties you specified. There's no need to specify the string type on each property--JavaScript will infer that for you.
While this is really easy to do, the drawback is that you're not going to get any type checking, so some code could inadvertently stick an object into one of your string fields and JavaScript won't stop it.
So just beware of the advantages and disadvantages of JavaScript's flexibility, and make sure you're doing server-side sanity checks on your data.
var items =
[
{
url: "http://...",
name: "FOO",
inputs: [
{
name: "Input1",
type: "LeTypeh"
value: "Levalueh"
},
{
name: "Input2 (Foo)",
type: "LeType2a",
value: "Levalue2j"
}
// ... (insert as many comma separated inputs as you need in the foo item
},
{
url: "http://...",
name: "BAR",
inputs: [
{
name: "Input1",
type: "LeTypeh"
value: "Levalueh"
},
{
name: "Input2 (Bar)",
type: "LeType2a",
value: "Levalue2j"
}
// ... (insert as many comma separated inputs as you need in the bar item here
}
//... (insert as many comma separated items as you need in the array here
]

Categories