Creating an object with values of JSON path - json

I implemented i18n with useTranslation and tried to make it easier for json path to be written.
JSON
{
"userInfo":{
"name": "Name",
"lastname": "Last Name"
},
"sideMenu:{
"home":"Home"
}
}
So now when I try to access translated text I go
t("userInfo.name", "Name")
I tried to make a function that will recursively call it self and create the object like this
object = {
userInfo: {
name: {
key:"userInfo.name",
value:"Name"
},
lastname: {
key:"userInfo.lastname",
value:"Last name"
},
},
sideMenu: {
home: {
key:"sideMenu.home",
value:"Home"
}
}
}
so now I could access like this
t(object.userInfo.name.key, object.userInfo.name.value)
I tried using entries and fromEntries function but I simply cant get hold of the logic behind it.

I made it work with a recursive function so now, no matter the number of nested objects function will return a new object with key and value items.
You can see working snippet with json file i used for the project.
let en = {
"userInfo":{
"name": "Name",
"lastname": "Last Name",
"gender": "Gender",
"age": "Age",
"location": "Location",
"address": "Address",
"city": "City",
"login": "Login",
"about": "About"
},
"comboBox": {
"loading": "Loading...",
"loadmore": "Load More"
},
"error": {
"errormsg": "Ooops, it seems you are not authenticated to see this...",
"errormsgsub": "Get back and try again",
"errorbtn": "Back to Safety",
"alertmsg": "You should login first!"
},
"sideMenu": {
"home": "Home",
"logout": "Logout",
"croatian": "Croatian",
"english": "English",
"hello": "Hello"
},
"loadingPage": {
"load": "Loading...",
"loadsub": "Please wait"
}
}
function languageRecursion(data, key){
if (typeof data === 'object') {
return Object.fromEntries(
Object.entries(data).map(([ikey, value]) => {
return [ikey, languageRecursion(value, key ? `${key}.${ikey}` : ikey)];
})
);
}
return { key: key, value: data };
}
let locale = languageRecursion(en)
console.log("path",locale.userInfo.about.key)
console.log("value", locale.userInfo.about.value)
With this working now you can call languages with i18next useTranslation hook faster and easier.
t(locale.userInfo.name.key)

Related

Nested JSON Schema Validation in Postman

I want to validate a Nested JSON Schema in Postman.
Here is the code.
const testSchema = {
"name": [
{
"first_name": "Alpha",
"last_name": "Bravo"
},
{
"first_name": "Charlie",
"last_name": "Delta"
},
],
"age": "23",
"color": "black"
};
const showData = {
"required": ["name", "age"],
"properties": {
"name": [
{
"required": ["first_name"]
}
],
},
};
pm.test("Nested Schema Test", function () {
pm.expect(tv4.validate(testSchema, showData)).to.be.true;
});
Currently, this code returns test as true.
I am unable to test the "name" array objects' keys.
Even upon passing this:
"required": ["fst_nae"] //wrong key name
it returns true.
I would just check in easy way via:
pm.test("your name", function () {
pm.expect(testSchema.name[0].first_name && testSchema.name[1].first_name
).to.eql('Alpha' && 'Charlie')
});
and you successfully validated these fields
or use this expect to organize your code of your choice
tiny validator i.e. tv4.validate is having issues in their library. Another option is to use AJV (you can search it on github).

MongoDB, NodeJS: updating an embedded document with new members

Using: MongoDB and native nodeJS mongoDB driver.
I'm trying to parse all the data from fb graph api, send it to my API and then save it to my DB.
PUT handling in my server:
//Update user's data
app.put('/api/users/:fbuser_id/:category', function(req, res) {
var body = JSON.stringify(req.body);
var rep = /"data":/;
body = body.replace(rep, '"' + req.params.category + '"' + ':');
req.body = JSON.parse(body);
db.fbusers.update({
id: req.params.fbuser_id
}, {
$set: req.body
}, {
safe: true,
multi: false
},
function(e, result) {
if (e) return next(e)
res.send((result === 1) ? {
msg: 'success'
} : {
msg: 'error'
})
});
});
I'm sending 25 elements at a time, and this code just overrides instead of updating the document.
Data I'm sending to the API:
{
"data": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Basically my API changes "data" key from sent json to the category name, f.e.:
PUT to /api/users/000/likes will change the "data" key to "likes":
{
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Then this JSON is put to the db.
Hierarchy in mongodb:
{
"_id": ObjectID("556584c8e908f0042836edce"),
"id": "0000000000000",
"email": "XXXX#gmail.com",
"first_name": "XXXXXXXX",
"gender": "male",
"last_name": "XXXXXXXXXX",
"link": "https://www.facebook.com/app_scoped_user_id/0000000000000/",
"locale": "en_US",
"name": "XXXXXXXXXX XXXXXXXXXX",
"timezone": 3,
"updated_time": "2015-05-26T18:11:59+0000",
"verified": true,
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
....and so on
}
]
}
So the problem is that my api overrides the field (in this case "likes") with newly sent data, instead of appending it to already existing data document.
I am pretty sure that I should be using other parameter than "$put" in the update, however, I have no idea which one and how to pass parameters to it programatically.
Use $push with the $each modifier to append multiple values to the array field.
var newLikes = [
{/* new item here */},
{/* new item here */},
{/* new item here */},
];
db.fbusers.update(
{ _id: req.params.fbuser_id },
{ $push: { likes: { $each: newLikes } } }
);
See also the $addToSet operator, it adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.

Groovy JSONBuilder issues

I'm trying to use JsonBuilder with Groovy to dynamically generate JSON. I want to create a JSON block like:
{
"type": {
"__type": "urn",
"value": "myCustomValue1"
},
"urn": {
"__type": "urn",
"value": "myCustomValue2"
},
"date": {
"epoch": 1265662800000,
"str": "2010-02-08T21:00:00Z"
},
"metadata": [{
"ratings": [{
"rating": "NR",
"scheme": "eirin",
"_type": {
"__type": "urn",
"value": "myCustomValue3"
}
}],
"creators": [Jim, Bob, Joe]
}]
}
I've written:
def addUrn(parent, type, urnVal) {
parent."$type" {
__type "urn"
"value" urnVal
}
}
String getEpisode(String myCustomVal1, String myCustomVal2, String myCustomVal3) {
def builder = new groovy.json.JsonBuilder()
def root = builder {
addUrn(builder, "type", myCustomVal1)
addUrn(builder, "urn", "some:urn:$myCustomVal2")
"date" {
epoch 1265662800000
str "2010-02-08T21:00:00Z"
}
"metadata" ({
ratings ({
rating "G"
scheme "eirin"
addUrn(builder, "_type", "$myCustomVal3")
})
creators "Jim", "Bob", "Joe"
})
}
return root.toString();
}
But I've run into the following issues:
Whenever I call addUrn, nothing is returned in the string. Am I misunderstanding how to use methods in Groovy?
None of the values are encapsulated in double (or single) quotes in the returned string.
Anytime I use a {, I get a '_getEpisode_closure2_closure2#(insert hex)' in the returned value.
Is there something wrong with my syntax? Or can someone point me to some example/tutorial that uses methods and/or examples beyond simple values (e.g. nested values within arrays).
NOTE: This is a watered down example, but I tried to maintain the complexity around the areas that were giving me issues.
You have to use delegate in addUrn method instead of
passing the builder on which you are working.
It is because you are doing a toSting() or toPrettyString() on root instead of builder.
Solved if #2 is followed.
Sample:
def builder = new groovy.json.JsonBuilder()
def root = builder {
name "Devin"
data {
type "Test"
note "Dummy"
}
addUrn(delegate, "gender", "male")
addUrn(delegate, "zip", "43230")
}
def addUrn(parent, type, urnVal) {
parent."$type" {
__type "urn"
"value" urnVal
}
}
println builder.toPrettyString()
Output:-
{
"name": "Devin",
"data": {
"type": "Test",
"note": "Dummy"
},
"gender": {
"__type": "urn",
"value": "male"
},
"zip": {
"__type": "urn",
"value": "43230"
}
}

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}

Validate Json Schema

I'm getting an error when using json-schema-validator API v4.
I try to do :
final JsonValidator validator = new JsonValidator(JsonLoader.fromPath("schema.json"));
ValidationReport report = validator.validate(data);
but every time I get an error : # [schema]: unknown keyword contacts
schema.json :
{
"contacts": {
"description": "The list of contacts",
"type": "array",
"optional": true,
"items": {
"description": "A contact",
"type": "object",
"properties": {
"givenName": {
"description": "Person's first name",
"type": "string",
"maxLength": 64,
"optional": true
},
"familyName": {
"description": "A person's last name",
"type": "string",
"maxLength": 64,
"optional": true
}
}
}
}
}
Regards
As far as I can intuit, your data looks like this-> json_data={"contacts":array}. If this is true, basically your outermost thing is an object (basically the full json object itself), for which you "might" need to define the schema starting from the "top level root" of your json as->
schema.json:
{
"description": "the outer json",
"type": "object",
"properties": {
"contacts": {
"description": "The list of contacts",
"type": "array",
"optional": true,
"items": {
"description": "A contact",
"type": "object",
"properties": {
"givenName": {
etc.....
Forgive me for rough indentations. Also, I have not tested this, please see if it works, if it does not, I would suggest you to provide your json_data (example at least) and the API's examples so that one can try to locate where what is wrong.
Use AVJ. Instead of having your data validation and sanitization logic written as lengthy code, you can declare the requirements to your data with concise, easy to read and cross-platform JSON Schema or JSON Type Definition specifications and validate the data as soon as it arrives to your application.
// validationSchema.js
import Ajv from "ajv";
import addFormats from "ajv-formats";
import ajvErrors from "ajv-errors";
const schemas = {
newUser: {
{
type: "object",
properties: {
lastName: {
type: "string",
minLength: 1,
maxLength: 255
},
firstName: {
type: "string",
minLength: 1,
maxLength: 255
},
description: {
type: "string"
},
birthday: {
type: "string",
format: "date-time"
},
status: {
type: "string",
enum: ["ACTIVE", "DELETED"]
},
},
required: ["name"]
}
}
};
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
ajvErrors(ajv /*, {singleError: true} */);
const mapErrors = (errorsEntry = []) => {
const errors = errorsEntry.reduce(
(
acc,
{ instancePath = "", message = "", params: { missingProperty = "" } = {} }
) => {
const key = (instancePath || missingProperty).replace("/", "");
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(`${key} ${message}`);
return acc;
},
[]
);
return errors;
};
const validate = (schemaName, data) => {
const v = ajv.compile(schemas[schemaName]);
let valid = false,
errors = [];
valid = v(data);
if (!valid) {
errors = mapErrors(v.errors);
}
return { valid, errors };
};
export default { validate };
You can validate it like this:
import validationSchema from "your_path/validationSchema.js"
const user = {
firstName: "",
lastName: "",
....
};
const { valid, errors = [] } = validationSchema.validate("newUser", user);
if(valid){
console.log("Data is valid!");
} else {
console.log("Data is not valid!");
console.log(errors);
}