I am calling an API using an AJAX call and then processing the response ready for output. THe only problem is, I cannot seem to access what looks like an array inside the response object and I can't for the life of me figure out why. It would seem just a basic thing to do but when I try and call the particular response value directly and log it in the console, it shows undefined.
Here is my response object:
{
format: "small",
_links: {
self: {
href: "http://www-*******.net/v1/trading/exchange"
}
},
_embedded: {
exchangeData: [
server: {
time: "10:01",
date: "08.12.2014"
},
expert: {
quantity: "48,069",
country: {
..................
Now, the variable I want to be accessing is the 'quantity' value of the 'expert' object. I thought this would be the way to get it:
response._embedded.exchangeData['expert'].quantity
IS this correct? It is not returning any value and I thought this is usually such a straightforward thing to do.
THanks
In JSON brackets [] are for arrays. For example, you could have ["a", "b", "c"], which you access with a numeric offset, such as response[1].
Curly braces {} are for objects (similar to hash tables in other languages), such as {"first": "a", "second": "b", "third": "c"}, which you access by referencing the property by name, such as response.first.
The notation is pretty simple, see the specification here.
In this case, you should fix the JSON source to read:
{
"_embedded": {
"exchangeData": {
"server": {
"time": "10:01",
"date": "08.12.2014"
},
"expert": {
"quantity": "48,069",
"country": {
Note that the character after exchangeData is now a curly brace, not a regular bracket. Then, you access it with:
response._embedded.exchangeData.expert.quantity
Related
I'm getting this JSON in the following format:
I want it like this:
What is the best way, in JS, to achieve this?
Getting JSON INPUT (for copy)
[{}, {
"unit_number": "111"
},
{
"residents": [{
"_id": "5dd690a9f3d9b1336a36f47b"
}]
},
{},
{
"tags_info": []
},
{},
{
"status": true
}
]
Required Outout JSON format (to copy)
[
{
"unit_number": "101",
"residents": [{
"_id": "5d5e8f503c7e8c6a08a4141a",
"firstname": "anubhav"
}],
"tags_info": [{
"_id": "59a6c7915415d3c30cadac62",
"tag_name": "Facebook Tagg"
}],
"status": true
}
]
I would first try to understand why the original backend implementation is written this way first. But to solve your immediate problem you can reduce the array of property values like so:
data.reduce((aggregate, value) => Object.assign(aggregate, value), {})
However, there is a caveat of doing this which is that any duplicate properties will be overridden by the latter property values. If that's not an issue Object.assign is perfect for this.
I am fetching some data via an API call (within my dataservicse.ts file) - and the response I get is a sort of complex JSON structure. I am able to fetch a specific part of the response as follows in my corresponding Component file as follows -
Here is one of the JSON object response that represents the general structure -
{
"address": {
"building": "1234",
"coord": [0, 0],
"street": "123 Main Street",
"zipcode": "00000"
},
"address2": "Test Suite 000",
"grades": [{
"grade": "A",
"score": 3
}, {
"grade": "B",
"score": 4
}, {
"grade": "A",
"score": 2
}],
"name": "John Doe",
"_id": "1212121"
}
Now - my goal is to acquire the 'name' attribute as well as the first 'grade' value within the grades attribute from each response object - and map them into separate Arrays so that I can display them in table columns using *ngFor.
This is my Component code
export class TestDataComponent implements OnInit {
name$: Object;
grade$: Object;
constructor(private data: DataService, private data2: DataService) { }
ngOnInit() {
//getAPIData is returning the API response from the dataservices.ts file
this.data.getAPIData().subscribe(
data=>console.log(data.response.map(name=>name.name))
); //this works fine - I get the names in an array
this.data2.getAPIData().subscribe(
data2=>console.log((data2.response.map(grade=>grade.grades)).map(grades
=> {grades.map((value, index) => value.grade})) //this returns an undefined value
);
}
Now - if I console.log((data2.response.map(grade=>grade.grades))
I get an Array of Array objects such as -
Array - [Array(3), Array(3), Array(2)]
and each of them consist of the 'grades' attribute Array of objects.
(taking the first array from above) -
Array(3)
0:{"grade": "A","score": 3}
1:{"grade": "B", "score": 4}
2:{"grade": "A", "score": 2}
Thus - I further map my initial response to achieve the 'grade' value. Also - I only want the first grade - thus I have a simple condition added as follows -
console.log((data2.response.map(grade=>grade.grades))
.map(grades
=> {grades.map((value, index) =>{if(index<1) value.grade})}))
As mentioned in the comment - I get an undefined value.
I undestand this issue may be fairly complex but I've tried my best to explain it as clearly as possible. My goal is to get the first 'grade' values from each object and display them in an Array - just as the names, so that I can use it to display it on a table.
I am fairly new to Angular6, just switching from Angular 1.6 - so I am pretty sure I am messing something up.
What would be the best way to get the grade values into an Array by nested mapping within subscribe? Or is there a better approach to the same ?
Also - for the sake of simplicity, ignore the fact that the first subscription is present (for the name attribute) - I showed it here so as to make it clear as to what I want to achieve.
Here is what I think you're asking for since you never gave a concrete example of what you're trying to map/reduce. Also, this is vanilla JavaScript but could easily be translated into RxJS.
// I am assuming that a call to `DataServce.getAPIData()` returns an array
const api_response = [{
"address": {
"building": "1234",
"coord": [0, 0],
"street": "123 Main Street",
"zipcode": "00000"
},
"address2": "Test Suite 000",
"grades": [{
"grade": "A",
"score": 3
}, {
"grade": "B",
"score": 4
}, {
"grade": "A",
"score": 2
}],
"name": "John Doe",
"_id": "1212121"
}];
// Map and pluck the values you need
const result = api_response.map(v => [v.name, v.grades[0].score])
// Or as an array of objects
const obj_result = result.map(([name, score]) => ({ name, score }))
// Is this what you want?
console.log('Array', result);
console.log('Objects', obj_result);
Quick Update
Thanks for accepting the answer. Just wanted to give a quick of what this might look like using RxJS. I say might because the code snippet below is untested.
this.nameAndScores$ = data.getAPIData().pipe(
map(({ response }) => response),
map(({ name, grades }) => ( { name, score: grades[0].score } ))
)
Assuming that nameAndScores$ is a property of your component instance, you can do *ngFor item in nameAndScores$ | async and avoid any explicit subscriptions in your code.
You are using curly braces with a fat arrow in second map function. While using curly braces, you should return a value using the return keyword.
I had this dictionary
"name" : {
"2016" : {
"1" : "info"
}
}
I added it to sessionStorage using json.stringfy and it worked perfectly. I then appended another dictionary to the first one:
name: {
2016: {
1: {
info: {
0: {
"question": "qs1",
"information": "info1"
},
1: {
"question": "qs12",
"information": "info2"
},
}
}
}
}
and I did the same convert to a string using json.stringfy. Then I noticed this:
name: {
0 : "2016",
1 : null,
2 : null, //until 2016
2016: {
1: {
info: {
0: {
"question": "qs1",
"information": "info1"
},
1: {
"question": "qs12",
"information": "info2"
},
}
}
}
I don't know why it's counting when the typeof tells me that it's a string, not a number. Also, I don't understand why it didn't do this with the first dictionary.
Here is the code:
(function($){
x = {
"info": {
"0": {
"question": "qs1",
"information": "info1"
},
"1": {
"question": "qs12",
"information": "info2"
},
}
}
var sesion = {};
var stringinfo;
sesion["name"]=["2016"];
sesion["name"]["2016"]=["1"];
sesion["name"]["2016"]["1"] = x;
stringinfo = json.stringfy(sesion);
console.log(sesion);
console.log(stringinfo)
}(jQuery))
Try it and tell me if using a number(string) as an index does that! How can I resolve this? Thank you.
you are confusing arrays ([]) and objects ({}). At the beginning you say:
I got this array:
"name" : {
"2016" : {
"1" : "info"
}
But this is an object.
Your question is a bit difficult to follow. But if you instantiate an empty array, and tell it that numer 2016 should have a certain value, it will fill up the rest with empty (null) values.
You want to use an object, rather than an array.
Look at your code where objects and arrays get mixed up. You want to be using an object, with the key "2016", not an array which uses numbers as indexes.
added information after reviewing supplied code
(btw I fixed spelling of 'sesion' to 'session' in explanation below)
the line:
var session = {}
makes an empty object. The line:
session["name"]=["2016"];
sets the property "name" of this object to be an array containing the only string "2016".
Now it gets interesting; you just made the name property an array, so the line
session["name"]["2016"]=["1"];
makes the compiler use the following logic; since session["name"] is an array, you probably don't mean to set a property on it when you refer to session["name"]["2016"]; the string "2016" gets coerced to a number and it puts a new array on it, containing the string "1".
At this point I must point out that your code is not running, and after fixing it the output is not like you put it in your question. What happens after is the same as before, just you put in the new array at the 1st spot your object in x.
The main problem in your code as stated before sits in mixing arrays and objects.
replace the line
session["name"]=["2016"];
for example with:
session["name"] = {}
to instantiate an object on which you can put properties such as "2016", and I am not sure what the exact objective is, but if you want to make an array under this property, do it something like:
session["name"]["2016"]=[x];
I have a "deep" JSON string that I need to pass as GET vars in a URL. It looks like the following:
{
"meta": {
"prune": true,
"returnFields": ["gf", "gh", "gh", "rt"],
"orient": "split"
},
"indicators": [{
"type": "beta",
"computeOn": "gf",
"parameters": {
"timeperiod": 5,
"nbdevup": 2,
"nbdevdn": 2,
"matype": 0
}
}, {
"type": "alpha",
"computeOn": "gf",
"parameters": {
"timeperiod": 30
}
}]
};
When encoding using jQuery.param, the result is as follows:
var recursiveEncoded = jQuery.param(body);
console.log(recursiveEncoded);
meta%5Bprune%5D=true&meta%5BreturnFields%5D%5B%5D=gf&meta%5BreturnFields%5D%5B%5D=gh&meta%5BreturnFields%5D%5B%5D=gh&meta%5BreturnFields%5D%5B%5D=rt&meta%5Borient%5D=split&indicators%5B0%5D%5Btype%5D=beta&indicators%5B0%5D%5BcomputeOn%5D=gf&indicators%5B0%5D%5Bparameters%5D%5Btimeperiod%5D=5&indicators%5B0%5D%5Bparameters%5D%5Bnbdevup%5D=2&indicators%5B0%5D%5Bparameters%5D%5Bnbdevdn%5D=2&indicators%5B0%5D%5Bparameters%5D%5Bmatype%5D=0&indicators%5B1%5D%5Btype%5D=alpha&indicators%5B1%5D%5BcomputeOn%5D=gf&indicators%5B1%5D%5Bparameters%5D%5Btimeperiod%5D=30
Which is decoded to the following:
var recursiveDecoded = decodeURIComponent( jQuery.param(body) );
console.log(recursiveDecoded);
meta[prune]=true&meta[returnFields][]=gf&meta[returnFields][]=gh&meta[returnFields][]=gh&meta[returnFields][]=rt&meta[orient]=split&indicators[0][type]=beta&indicators[0][computeOn]=gf&indicators[0][parameters][timeperiod]=5&indicators[0][parameters][nbdevup]=2&indicators[0][parameters][nbdevdn]=2&indicators[0][parameters][matype]=0&indicators[1][type]=alpha&indicators[1][computeOn]=gf&indicators[1][parameters][timeperiod]=30
If just using a serialized string result on the server leaves the string as the key in a key value pair:
"query": {
"{\"meta\":{\"prune\":true,\"returnFields\":[\"gf\",\"gh\",\"gh\",\"rt\"],\"orient\":\"split\"},\"indicators\":[{\"type\":\"beta\",\"computeOn\":\"gf\",\"parameters\":{\"timeperiod\":5,\"nbdevup\":2,\"nbdevdn\":2,\"matype\":0}},{\"type\":\"alpha\",\"computeOn\":\"gf\",\"parameters\":{\"timeperiod\":30}}]}": ""
},
My backend processing is done with Python. What modules exist to convert the above result to a dict resembling the original object?
Well, since we hashed it out in the comments, I'll post the answer here for posterity.
Use a combination of JSON.stringify on the JavaScript side to serialize your data structure and json.loads on the Python side to deserialize it. Pass the serialized structure as a query string parameter ("query" in your example) and then read the value from that query string parameter in Python. Huzzah!
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
I have following json:
{
"responseHeader": {
"status": 0,
"QTime": 1
},
"spellcheck": {
"suggestions": [
"a",
{
"numFound": 4,
"startOffset": 0,
"endOffset": 1,
"suggestion": [
"api",
"and",
"as",
"an"
]
},
"collation",
"api"
]
}
}
I want to access the 'suggestion' array and for that I am using this in jQuery:
$.getJSON('http://localhost:8983/solr/suggest/?q=' + query + '&wt=json&json.wrf=?', {
})
.done(function(response){
// just for testing
alert(response.spellcheck.suggestions.suggestion); // error: response.spellcheck is not defined
});
The value of 'response.spellcheck' is shown undefined whereas 'response.responseHeader' shows [object Object] and also I can access elements under responseHeader. But I cannot figure out what's the issue with 'spellcheck'. Help!
suggestions.suggestions can't work. suggestions is an array. You need to index the array with the [] operator to get to a specific suggestion.
Specifically, based on the JSON you posted, you want suggestions[1].suggestion.
use console.log for printing the response then you can do accordingly
The correct spelling is response.spellcheck.suggestions (you have used suggesstions) and this is an array, so you can look at its context using the index... for example:
alert(response.spellcheck.suggestions.suggestion[0]); // "a"
So you need:
response.spellcheck.suggestions.suggestion[1].suggestion
Example on JS Fiddle.