NodeJS: Adding new child nodes to JSON Object - json

lets say there is customer object, i need to add new element address to this json object customer. how can I achieve this?
Both of these are not altering the customer JSON object
customer['address'] = addressObj
customer.address = addressObj
and I can not use push() as this is not adding a new item in list of objects.
Thanks,
Naren

Maybe your addressObj is not properly formed.
This works for me:
var customer = {"name": "Naren"};
customer.address1 = "stackoverflow";
customer.address2 = {"fulladdress":"stackoverflow"};
JSON.stringify(customer)
Output:
"{"name":"Naren","address1":"stackoverflow","address2":{"fulladdress":"stackoverflow"}}"

Maybe I am not clear on what exactly you want to do but it sounds to me as if you want have a JSON and want to merge it with another JSON, creating just a JSON file.
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
You now want to add Supergirl (the new element) to Superman (the old element) I assume. Take a look here # merge-json a simple package which does its job well. You would code as follows:
use strict;
var mergeJSON = require("merge-json");
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
let Json6 = mergeJSON(Json1,Json2);
Json6=mergeJSON(Json6,Json3);
You would end up with as follows:
Json6 = {'Superman': 'Favorite', 'Supergirl': 'Greatest', 'IronFist': 'Top 10'}
This is how I make use of combining JSON information or text information into a JSON file. You can get much more sophisticated with the module mentioned above. (Just do not confuse merge-json with json-merge and other modules.)
If this is not what you are looking for my apologies, then I did not understand the question correctly.

Related

Trying to make a command to store and retreat info from a json file

Im trying to make a command that will store name,description and image of a character and another command to retrieve that data in an embed,but i have trouble working with json files
this is my code to add them:
#client.command()
async def addskillset(ctx):
await ctx.send("Let's add this skillset!")
questions = ["What is the monster name?","What is the monster description?","what is the monster image link?"]
answers = []
#code checking the questions results
embedkra = nextcord.Embed(title = f"{answers[0]}", description = f"{answers[1]}",color=ctx.author.color)
embedkra.set_image(url = f"{answers[2]}")
mess = await ctx.reply(embed=embedkra,mention_author=False)
await mess.add_reaction('✅')
await mess.add_reaction('❌')
def check(reaction, user):
return user == ctx.author and (str(reaction.emoji) == "✅" or "❌")
try:
reaction, user = await client.wait_for('reaction_add', timeout=1000.0, check=check)
except asyncio.TimeoutError:
#giving a message that the time is over
else:
if reaction.emoji == "✅":
monsters = await get_skillsets_data() #this data is added at the end
if str(monster_name) in monsters:
await ctx.reply("the monster is already added")
else:
monsters[str(monster_name)]["monster_name"] = {}
monsters[str(monster_name)]["monster_name"] = answers[0]
monsters[str(monster_name)]["monster_description"] = answers[1]
monsters[str(monster_name)]["monster_image"] = answers[2]
with open('skillsets.json','w') as f:
json.dump(monsters,f)
await mess.delete()
await ctx.reply(f"{answers[0]} successfully added to the list")
Code to get the embed with the asked info:
#client.command()
async def skilltest(ctx,*,monster_name):
data = open('skillsets.json').read()
data = json.loads(data)
if str(monster_name) in data:
name = data["monster_name"]
description = data["monster_description"]
link = data["monster_image"]
embedkra = nextcord.Embed(title = f"{name}", description = f"{description}",color=ctx.author.color)
embedkra.set_image(url = f"{link}")
await ctx.reply(embed=embedkra,mention_author=False)
else:
# otherwise, it is still None meaning we didn't find it
await ctx.reply("monster not found",mention_author=False)
and my json should look like this:
{"katufo": {"monster_name": "Katufo","Monster_description":"Katufo is the best","Monster_image":"#image_link"},
"armor claw":{"monster_name": "Armor Claw","Monster_description":"Armor claw is the best","Monster_image":#image_link}}
The get_skillsets_data used in first command:
async def get_skillsets_data():
with open('skillsets.json','r') as f:
monsters = json.load(f)
return monsters
Well, When you are trying to retrieve data from your json file try using name = data["katufo"]["monster_name"] now here it will only retrieve monster_name of key katufo. If You want to retrieve data for armor claw code must go like this name = data["armor claw"]["monster_name"]. So try this code :
#client.command()
async def skilltest(ctx,*,monster):
data = open('skillsets.json').read()
data = json.loads(data)
if str(monster) in data:
name = data[f"monster"]["monster_name"]
description = data[f"monster"]["Monster_description"]
link = data[f"monster"]["Monster_image"]
embedkra = nextcord.Embed(title = f"{name}", description = f"{description}",color=ctx.author.color)
embedkra.set_image(url = f"{link}")
await ctx.reply(embed=embedkra,mention_author=False)
else:
# otherwise, it is still None meaning we didn't find it
await ctx.reply("monster not found",mention_author=False)
Hope this works for you :)
If your json looks like what you showed above,
{
"katufo":{
"monster_name":"Katufo",
"Monster_description":"Katufo is the best",
"Monster_image":"#image_link"
},
"armor claw":{
"monster_name":"Armor Claw",
"Monster_description":"Armor claw is the best",
"Monster_image":"#image_link"
}
}
then there is no data["monster_name"] the two objects inside of your JSON are named katufo and armor_claw. To get one of them you can simply write data['katufo']['monster_name'] or data.katufo.monster_name.
Your problem stems from looking up the monster name like this:
if str(monster_name) in data:
name = data["monster_name"]
description = data["monster_description"]
link = data["monster_image"]
What you could do instead is loop through data, as it contains several monsters and then on each object, to the check that you do:
for monster in data:
if str(monster_name) in monster.values():
name = monster.monster_name
description = monster.Monster_description
link = monster.Monster_image
One thing to think about, the way the variables are named is not something I personally recommend. Don't be afraid of adding longer descriptive names so things make more sense for you in the code. Also, in the JSON you provided, there are certain attributes starting with a capital letter, something you should think about.
Edit:
Dicts in python are the equivalent of objects in Javascript and are initialized using the same syntax which we can see below:
monster_data = {}
But since you want a specific structure on these monsters we can go further and create a function called add_monster_object():
def add_monster_object(original_dict, new_monster):
new_monster = {
"monster_name": '',
"monster_description": '',
"monster_image": ''
}
#Now we have a new empty object with the correct names.
return original_dict.update(new_monster)
Now every time you run this function with a given name, in the dict there will be an object with that name. Example is if user writes armor_sword as the monster_name attribute, then we can call the function above as add_monster_object(original_dict, monster_name).
This will, if we take your initial dict as an example, return this:
{
"katufo":{
"monster_name":"Katufo",
"Monster_description":"Katufo is the best",
"Monster_image":"#image_link"
},
"armor claw":{
"monster_name":"Armor Claw",
"Monster_description":"Armor claw is the best",
"Monster_image":"#image_link"
},
"armor sword":{
"monster_name":"",
"monster_description":"",
"monster_image":""
}
}
Then you can populate them as you want, or update the function to take more parameters. The important part here is that you take a minute and figure out what you want to keep saved. Then make sure that you can read and write from file and you should have a somewhat simple structure going. Warning: This isn't a slap and dry method, you will also have to think about special cases, such as adding an object that already exists and soforth.
If you decide to go with Replit you could use their database to create similar functionality but you wouldn't have to worry about reading and writing to a file.
As it is right now, I still think you need to proceed with your bot, add some of the changes that I mentioned before the next actual problem arrives as there are many things that arent quite right. I also suggest you break everything into managing parts, 1 would be to read from a file. 2 would be to write. 3 to write a dict to a file. 4 to update a dict and soforth. Good luck!

How can I get access to multiple values of nested JSON object?

I try to access to my data json file:
[{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}
This is my approach:
data[0].name;
But like this I get only the result:
Animals
But I would need the result:
Animals, Cats
You are accessing only the name property of 0th index of project array.
To access all object at a time you need to loop over the array.
You can use Array.map for this.
var data = [{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}]
var out = data[0].project.map(project => project.name).toString()
console.log(out)
If that's your actual data object, then data[0].name would give you "Maria". If I'm reading this right, though, you want to get all the names from the project array. You can use Array.map to do it fairly easily. Note the use of an ES6 arrow function to quickly and easily take in the object and return its name.
var bigObject = [{"id":1,"name":"Maria","project":[{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}]}];
var smallObject = [{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}];
console.log("Getting the names from the full array/data structure: "+bigObject[0].project.map(obj => obj.name))
console.log("Getting the names from just the project array: "+smallObject.map(obj => obj.name))
EDIT: As per your comment on the other answer, you said you needed to use the solution in this function:
"render": function (data, type, row) {if(Array.isArray(data)){return data.name;}}
To achieve this, it looks like you should use my bottom solution of the first snippet like so:
var data = [{"id":5,"name":"Animals"},{"id":6,"name":"Cats"}];
function render(data, type, row){
if(Array.isArray(data)){
return data.map(obj => obj.name);
}
};
console.log("Render returns \""+render(data)+"\" as an array.");

Which JSONPath expression should I use to split my JSON string?

I want to apply SplitJson in order to split the following JSON file into 2 FlowFiles (according to hits):
{"took":0,"timed_out":false,"_shards":
{"total":5,"successful":5,"failed":0},
"hits":{"total":2,"max_score":0.0,
"hits":
[
{"_index":"my_index","_type":"my_entry","_id":"111","_score":0.0,"_source":{"ZoneId":"1","OriginId":"1"},
"fields":{"ttime":[11000]}},
{"_index":"my_index","_type":"my_entry","_id":"222","_score":0.0,"_source":{"ZoneId":"1","OriginId":"2"},
"fields":{"ttime":[5000]}}
]
}
}
Which JsonPath Expression should I use? I tried $.hits[*], but it splits the content according to the first level hits. In my case I have hits[hits[...]], but how should I specify it in the expression?
UPDATE:
I want to get two FlowFiles:
FlowFile #1: {"_index":"my_index","_type":"my_entry","_id":"111","_score":0.0,"_source":{"ZoneId":"1","OriginId":"1"},"fields":{"ttime":[11000]}}
FlowFile #2:
{"_index":"my_index","_type":"my_entry","_id":"222","_score":0.0,"_source":{"ZoneId":"1","OriginId":"2"},"fields":{"ttime":[5000]}}
var arr = $.hits.hits;
Will give you the array with 2 objects you desire.
var o1 = arr[0];
var o2 = arr[1];
Will give you 2 objects you desire.
var json1 = JSON.stringify(arr[0]);
var json2 = JSON.stringify(arr[1]);
Will give you 2 JSON files as requested.
Is this what you needed?
You can use this website for testing JSONPath Index for your case.
The right answer is $.hits.hits[*].
As mentioned DanteTheSmith, you can simply use $.hits.hits in your case. It depends on the post-processing. Both methods work fine.

Swift: Firebase updateChildValues function Overwriting and Deleting Other Keys at Location

I am running into a peculiar issue when trying to simultaneously update values at different JSON branches in Firebase. The method provided in the documentation is perfect when it comes to creating new data,
let key = ref.child("posts").childByAutoId().key
let post = ["uid": userID,
"author": username,
"title": title,
"body": body]
let childUpdates = ["/posts/\(key)": post,
"/user-posts/\(userID)/\(key)/": post]
ref.updateChildValues(childUpdates)
but when I try to update data at multiple locations, it overwrites the other keys as if I was using setValue. Here is my code.
let userID = Auth.auth().currentUser?.uid
userRef = Database.database().reference()
let vehicle = ["make":make.text,
"model": model.text,
"year":year.text,
"color":color.text,
"doors":doors.text]
let driver = ["currentEvent":eventID]
let childUpdates = ["/users/\(userID!)": driver,
"/status/\(userID!)/driverInfo/vehicle": vehicle]
userRef.updateChildValues(childUpdates)
I have also attached a picture which shows which data is and isn't being deleted when the function is executed.
I believe what I am trying to do is possible, and from what I understand the whole purpose of updateChildValues is so that other children aren't overwritten.
Any help is appreciated. Thanks!
Currently you are updating the objects with objects like this:
let childUpdates = ["/users/\(userID!)": driver,
"/status/\(userID!)/driverInfo/vehicle": vehicle]
You are giving the object (a dictionary) as the value of the childUpdates dictionary. What this does is that replace all the children with this object meaning deleting the values for which you are sending nil for example in your case you have not included info or infoThat .
Now if you want to change only the values you want to give like only change the value of say make and model for vehicle and currentEvent for driver , you have to give the particular path for these values
["/users/\(userID!)/currentEvent": eventID,
"/status/\(userID!)/driverInfo/vehicle/make": make.text, "/status/\(userID!)/driverInfo/vehicle/model": model.text]
I think this will update the values of these locations as you expected.
HTH...
Correct me if I am mistaken, but if I understand what you're trying to do this might yield better results?
let userID = Auth.auth().currentUser?.uid
userRef = Database.database().reference()
let vehicle = ["make":make.text,
"model": model.text,
"year":year.text,
"color":color.text,
"doors":doors.text]
let driver = ["currentEvent":eventID]
let childUpdates = ["/users/": userID!),
"/status/\(userID!)/driverInfo": vehicle]
userRef.updateChildValues(childUpdates)

Regular expression to extract a JSON array

I'm trying to use a PCRE regular expression to extract some JSON. I'm using a version of MariaDB which does not have JSON functions but does have REGEX functions.
My string is:
{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}
I want to grab the contents of category. I'd like a matching group that contains 2 items, Jebb and Bush (or however many items are in the array).
I've tried this pattern but it only matches the first occurrence: /(?<=category":\[).([^"]*).*?(?=\])/g
Does this match your needs? It should match the category array regardless of its size.
"category":(\[.*?\])
regex101 example
JSON not a regular language. Since it allows arbitrary embedding of balanced delimiters, it must be at least context-free.
For example, consider an array of arrays of arrays:
[ [ [ 1, 2], [2, 3] ] , [ [ 3, 4], [ 4, 5] ] ]
Clearly you couldn't parse that with true regular expressions.
See This Topic:
Regex for parsing single key: values out of JSON in Javascript
Maybe Helpful for you.
Using a set of non-capturing group you can extract a predefined json array
regex answer: (?:\"category\":)(?:\[)(.*)(?:\"\])
That expression extract "category":["Jebb","Bush"], so access the first group
to extract the array, sample java code:
Pattern pattern = Pattern.compile("(?:\"category\":)(?:\\[)(.*)(?:\"\\])");
String body = "{\"device_types\":[\"smartphone\"],\"isps\":[\"a\",\"B\"],\"network_types\":[],\"countries\":[],\"category\":[\"Jebb\",\"Bush\"],\"carriers\":[],\"exclude_carriers\":[]}";
Matcher matcher = pattern.matcher(body);
assertThat(matcher.find(), is(true));
String[] categories = matcher.group(1).replaceAll("\"","").split(",");
assertThat(categories.length, is(2));
assertThat(categories[0], is("Jebb"));
assertThat(categories[1], is("Bush"));
There are many ways. One sloppy way to do it is /([A-Z])\w+/g
Please try it on your console like
var data = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}',
res = [];
data.match(/([A-Z])\w+/g); // ["Jebb", "Bush"]
OK the above was pretty sloppy however a solid single regex solution to extract every single element regardless of the number, one by one and to place them in an array (res) is the following...
var rex = /[",]+(\w*)(?=[",\w]*"],"carriers)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
arr = [],
res = [];
while ((arr = rex.exec(str)) !== null) {
res.push(arr[1]); // <- ["Jebb", "Bush", "Donald", "Trump"]
}
Check it out # http://regexr.com/3d4ee
OK lets do it. I have come up with a devilish idea. If JS had look-behinds this could have been done simply by reversing the applied logic in the previous example where i had used a look-forward. Alas, there aren't... So i decided to turn the world the other way around. Check this out.
String.prototype.reverse = function(){
return this.split("").reverse().join("");
};
var rex = /[",]+(\w*)(?=[",\w]*"\[:"yrogetac)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
rev = str.reverse();
arr = [],
res = [];
while ((arr = rex.exec(rev)) !== null) {
res.push(arr[1].reverse()); // <- ["Trump", "Donald", "Bush", "Jebb"]
}
res.reverse(); // <- ["Jebb", "Bush", "Donald", "Trump"]
Just use your console to confirm.
In c++ you can do it like this
bool foundmatch = false;
try {
std::regex re("\"([a-zA-Z]+)\"*.:*.\\[[^\\]\r\n]+\\]");
foundmatch = std::regex_search(subject, re);
} catch (std::regex_error& e) {
// Syntax error in the regular expression
}
If the number of items in the array is limited (and manageable), you could define it with a finite number of optional items. Like this one with a maximum of 5 items:
"category":\["([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)")?)?)?)?
regex101 example here.
Regards.