Using string in referencing JSON object in request - javascript

Using a fetch request to get some data. The JSON object path depends on a string variable. How would I convert the string into an object that can be referenced as an array in the path. Here's my code:
var path = 'bob';
fetch(request)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
}).then(function(json) {
var data = json.message.path[0].text;
}).catch(function(error) {
console.log(error);
});
JSON:
{
"message": {
"bob": [
{
"name_id": "3351",
"name": "bob",
"text": "lorem ipsum"
},
{
"name_id": "34562",
"name": "bob",
"text": "lorem ipsum2"
}
]
}
Basically, path defines the correct object to be used in the dot notation. BUT - the object also has to be able to reference the array.
Any solutions?

You could try using:
var data = json.message[path][0].text;
where path is the name of the object as you defined:
path = "bob";

If you have a path variable in the format user.index, you could reference the corresponding message in your JSON like this:
path = path.split(".");
var name = path[0], index = path[1];
var data = json.message[name][index].text;
If path is "bob.1", data would become "lorem ipsum2"
json.message[name] evaluates to the array of messages. To index into that array, just put brackets after the value, like any other array: json.message[name][index], which is equivalent to (json.message[name])[index], which is equivalent to var array = json.message[name] then array[index].
Note that this solution does no error checking, and will throw an error if the given user isn't in json.message.

Related

Getting error: Cannot read properties of undefined in javascript

While calling function getting error:
Uncaught TypeError: Cannot read properties of undefined (reading 'username')
at getLoginData (<anonymous>:3:30)
at <anonymous>:1:1"
role1 has value "administrator", but why it is not able to call in datamodel? (Datamodel here refers is another JSON file)
datamodel = {
administrator: [
{
username: "abc#xyz.com",
password: "abc#1234",
},
{
username: "abcd#xyz.com",
password: "xyz#1234",
},
],
};
function getLoginData(role1) {
console.log(role1);
let name = datamodel.role1.username;
}
getLoginData("administrator[0]");
You can't access object in that was, the code thinks that role1 is a key in that Object.
function getLoginData(role1){
console.log(role1)
let name=datamodel[role1][0].username
}
getLoginData("administrator")
var datamodel = {
"administrator": [
{
"username": "abc#io.com",
"password": "abc#1234"
},
{
"username": "xyz#io.com",
"password": "xyz#1234"
}
]
}
console.log(datamodel);
var name = datamodel.administrator[0].username; //get the name of administrator[0] = "rinty.kurian#espacenetworks.io"
console.log(name);
Try this :)
First of all you need to use Brackets Notation to access an object's attribute that is stored inside of another variable. So assuming you want the first credentials from the administrators array you would write something like datamodel.administrator[0].
Since, as it seems from your function's call, getLoginData('administrator[0]'), you would like that the function getLoginData to take care of accessing the inner administrators array which we cannot directly using brackets notation as datamodel['administrators[0]'] will raise an error because the attribute "administrators[0]" (string) doesn't exist in the datamodel object.
What we need to do is to try to extract the index of the items we want to return, if it exists, and then use that to return the right credentials from the datamodel object.
To do so, we will split the argument that is passed to getLoginData to get the attribute we want to access (ex: administrators) and the index (ex: 0).
Here's a live demo to implement such functionality:
const dataModel = {
"administrator": [{
"username": "abc#xyz.com",
"password": "abc#1234"
},
{
"username": "abcd#xyz.com",
"password": "xyz#1234"
}
]
},
/**
* a function that accepts an attribute name and optional index to get from "datamodel" object
*/
getLoginData = role => {
/**
* split the role parameter to get the wanted index if there is one
* the trick here is that we will replace the brackets around the index with a space and only keep the index itself (we'll get rid of those brackets)
* we should make some checks to prevent undefined index like errors
*/
const splitted = role.replace(/\[(\d+)\]/, ' $1').split(' '),
attr = dataModel[splitted[0]] ? (splitted.length > 1 ? dataModel[splitted[0]][splitted[1]] : dataModel[splitted[0]]) : null;
/** return the appropriete attribute or null if not defined */
return attr ? attr.username : null;
};
// prints: "abc#xyz.com"
console.log(getLoginData("administrator[0]"))
UPDATE
Here's another possible solution that works by passing the item index as the second parameter to datamodel object.
const dataModel = {
"administrator": [{
"username": "abc#xyz.com",
"password": "abc#1234"
},
{
"username": "abcd#xyz.com",
"password": "xyz#1234"
}
]
},
/**
* a function that accepts an attribute name and an index to get from "datamodel" object
*/
getLoginData = (role, index) => dataModel[role] && dataModel[role][index] ? dataModel[role][index].username : null;
// prints: "abc#xyz.com"
console.log(getLoginData("administrator", 0))

JSON Parse nested objects in React

I'm fetching data in React from a MySQL database. MySQL auto-escapes my values including nested objects. I'm using the .json() function on the top-level but i'm not able to use this on sub-levels, nor JSON.parse(response[0].data) will work.
What is the right way of doing this?
fetch(`http://localhost:3000/getQuiz${window.location.pathname}`, requestOptions)
.then(response => response.json())
.then(response => {
console.log(response)
// {
// "id": 1,
// "url": "asd2q13",
// "data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
// }
console.log(typeof response)
// object
console.log(response[0].data)
// {name: "Marie", answers:["1", "3", "0"]}
console.log(typeof response[0].data)
// string
console.log(response[0].data.name)
// undefined
})
The response.data is not a valid JSON string. You can try:
const response = {
"id": 1,
"url": "asd2q13",
"data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
}
console.log(eval('(' + response.data + ')'))
Or Better:
const response = {
"id": 1,
"url": "asd2q13",
"data": "{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}"
}
function looseJsonParse(obj) {
return Function('"use strict";return (' + obj + ')')();
}
console.log(looseJsonParse(response.data))
But,
Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!, below.
I suggest you serialize the data correctly on the backend. I think the MySQL database driver can do this. Also, see Parsing JSON (converting strings to JavaScript objects)
MySQL (MySQL2) for Node was the big problem here. It's suppose to serialize "automatically", but somehow it ends up all wrong.
If I do JSON.Stringify() explicitly for the nested part before storeing it in the database it works!
const sendToDatabase = () => {
let nested = JSON.stringify({ name: "Marie", answers: ["2", "1", "0"] })
let post = { url: "asd2q13", data: nested}
var query = connection.query(
"INSERT INTO users SET ? ", post,
function (error, results, fields) {
if (error) throw error;
}
);
console.log(query.sql);
};
Then I call this on the front end
console.log(JSON.parse(response[0].data).name)
// Marie (string)
console.log(JSON.parse(response[0].data).answers)
// ["2", "1", "0"] (array)
The raw output from this is
{"name":"Marie","answers":["2","1","0"]}
insted of
{name: \"Marie\", answers:[\"1\", \"3\", \"0\"]}

How do I find a JSON value with a specific ID?

I have an object and I’m trying to find a specific value using an ID in ECMAScript6.
I’ve tried something like this: myvalue = this.json.find(x => x == '1234');
The JSON looks something like this:
{
"results": [
{
"abcde1234": {
"value": 4
}
},
{
"zxcv4567": {
"value": 2
}
}
]
}
All the examples I’ve found can only find off named key-value pairs.
Try
json.results.find(x => /1234/.test(Object.keys(x)[0]));
json = {
"results": [
{
"abcde1234": {
"value": 4
}
},
{
"zxcv4567": {
"value": 2
}
}
]
}
let r = json.results.find(x => /1234/.test(Object.keys(x)[0]));
console.log(r);
const json = {
'1234': { 'value' : 4},
'5678': { 'value' : 10}
};
const value = json['1234'];
console.log(value);
The JSON data doesn't seem proper.
But in case you are finding by key, you can directly access this, something like:
Parsed JSON maps directly to JavaScript types: Object, Array, boolean, string, number, null. Your example used find() which is (normally) a method used with arrays. If your JSON was structured like this, you could expect to use find:
const jsonString = '["a", "b", "c"]';
const jsonData = JSON.parse(jsonString);
jsonData.find(x => x === "a"); // "a"
But it seems like your data is structured as an object, so you can use normal property access:
const jsonString = '{"1234": {"value": 4}, "5678": {"value": 10}}';
const jsonData = JSON.parse(jsonString);
jsonData["1234"] // {value: 4}
jsonData["1234"].value // 4
EDIT
OP changed the data example, so the above code is less directly applicable, but the general point is: once you parse it, it's just javascript.

How to parse all JSON strings in a JavaScript object

I have 1 JavaScript object like this:
result = {
"status": "success",
"message": "Get successful!",
"data": {
"name":"Hello world",
"school": {
"name":"LHP",
"address":"HCM"
},
"class": "[{\"text\":\"Math\",\"code\":\"math124\"},{\"text\":\"Libra\",\"code\":\"libra124\"}]",
"student": "{\"time_range\":{\"type\":\"select\",\"text\":\"Today\",\"value\":[{\"code\":\"in_today\",\"text\":\"In Today\"}]}}"
}
}
So I have to parse class and student separately:
result.data.class = JSON.parse(result.data.class);
result.data.student = JSON.parse(result.data.student);
Is there other way to parse the whole result variable or make this step shorter/better?
Thanks
You could loop through the data property's children and parse them.
for (var i = 0; i < Object.keys(result.data).length; i++) {
try {
result.data[Object.keys(result.data)[i]] = JSON.parse(result.data[Object.keys(result.data)[i]]);
} catch (error) {} // it's already JSON
}
But I'd only do that if you're sure you'll only ever have to deal with stringified JSON in the data property of your object.

Google Postman: How to get properties of an Array

I've got a problem by checking this json properties. I want to test, if the formName is "TestForm_WF1", but I dont know how to write the test to check the properties of this strange named array:
{
"#!#": [
{
"_type": "wfdocument",
"formName": "TestForm_WF1",
normally I got some Output like
[
{
"_type": "application",
...
which I could test with the following forEach-function:
var response = JSON.parse(responseBody);
response.forEach( function(entry) {
test["foo"] = entry._type === "application";
...
});
other way round was that properties have thier own properties and could be tested like:
Output:
{
"license": {
"_type": "license",
...
Testcase:
var jsonData = JSON.parse(responseBody);
tests["bar"] = jsonData.license._type === "license";
Use a bracket notation for characters that can't be used with a dot notation:
var response = JSON.parse(responseBody);
response["#!#"].forEach( function(entry) {
test["foo"] = entry._type === "application";
...
});

Categories