Why console.log does not show all levels of JSON after parsing? - json

I am practicing with simple APIs. I request data from OXFORD API. The data is received correctly and I can navigate through it and extract the definitions or etymologies I want. However when I print the complete response after the .json() the content of some arrays is shown as [Array]. Any Idea what I am missing?
My code looks like this:
let endpoint = "https://od-api.oxforddictionaries.com/api/v2/entries/en-gb/ace?fields=definitions&strictMatch=false";
const headers: {
'app_id': app_id,
'app_key': app_key
}
fetch(endpoint, {headers} )
.then(rawResponse=>rawResponse.json())
.then(response=>{
console.log(response);
console.log(response.results[0].lexicalEntries[0].entries[0].etymologies[0])
});
Result in the console looks like:
'''
{
id: 'ace',
metadata: {
operation: 'retrieve',
provider: 'Oxford University Press',
schema: 'RetrieveEntry'
},
results: [
{
id: 'ace',
language: 'en-gb',
lexicalEntries: [Array],
type: 'headword',
word: 'ace'
},
{
id: 'ace',
language: 'en-gb',
lexicalEntries: [Array],
type: 'headword',
word: 'ace'
}
],
word: 'ace'
}
Middle English (denoting the ‘one’ on dice): via Old French from Latin as ‘unity, a unit’
'''
I had tried with Apps Script, I got same result
'''
results:
[ { id: 'ace',
language: 'en-gb',
lexicalEntries: [Object],
type: 'headword',
word: 'ace' },
'''
Thanks in advance

The first comment here inspired my answer and further search. console.log() mainly prints string and when passing to it an array or an object, it interpret them as far as it can. So for the first level of [object, object] or {A:[],B:[]} it would print it without a problem.
When we go deeper to more nested arrays and objects within the JavaScript object parsed from an API response, it won't be able to interpret it properly and would return [object] or [Array]
e.g. The following can be printed by console.log easily
console.log([{A:1},{B:2},{C:3}])
and returns
[ { A: 1 }, { B: 2 }, { C: 3 } ]
Also,
console.log([{A:1},{B:2},{C:3,D:[1,2,3]}])
easily prints
[ { A: 1 }, { B: 2 }, { C: 3, D: [ 1, 2, 3 ] } ]
But,
console.log([{A:1},{B:2},{C:3,D:[{E:1},{F:2},{G:3}]}])
returns
[ { A: 1 },
{ B: 2 },
{ C: 3, D: [ [Object], [Object], [Object] ] } ]
So we need, to use JSON.stingify to convert it into a string
console.log(JSON.stringify([{A:1},{B:2},{C:3,D:[{E:1},{F:2},{G:3}]}]))
Successfully returns
[{"A":1},{"B":2},{"C":3,"D":[{"E":1},{"F":2},{"G":3}]}]
However, When the JSON object is bigger and deeper, you might need to prettify it using
console.log(JSON.stringify([{A:1},{B:2},{C:3,D:[{E:1},{F:2},{G:3}]}],null,2))
it returns
[
{
"A": 1
},
{
"B": 2
},
{
"C": 3,
"D": [
{
"E": 1
},
{
"F": 2
},
{
"G": 3
}
]
}
]
You can find a reference in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

Related

How do you destructure objects nested in an array

I understand how destructuring work, {item}=data logs the item from data and [item]=data does the same. If its an object nested in an array, we do [{item}]=data. I have tried to destructure my data with no luck, so I thought to come on here and seek for help.
From the below data, how do you destructure the keys nested in payload.
const events = {
data: [
{
payload: {
care_recipient_id: "df50cac5-293c-490d-a06c-ee26796f850d",
caregiver_id: "220d9432-b5ed-4c81-8709-434899d2cd1b",
consumed_volume_ml: 230,
event_type: "fluid_intake_observation",
fluid: "caffeinated",
id: "00114a9f-00dc-4f39-a6ac-af1b7e0543e7",
observed: false,
timestamp: "2019-04-26T07:08:21.758Z",
visit_id: "5cc23bf0-8b66-f8a8-4339-688e1d43e11a",
},
payload: {
care_recipient_id: "df50cac5-293c-490d-a06c-ee26796f850d",
caregiver_id: "5c9090ab-7d5e-4a72-8bf7-197190ad4c98",
event_type: "task_completed",
id: "006139b8-a387-4529-9280-2d798c500aeb",
task_definition_description: "Assist with oral hygiene",
task_definition_id: "1bf3b81d-40b0-4539-ba96-9ea12ad6110b",
task_instance_id:
"dHxmMjU2YmFlYS1jODEyLTRjZWMtOTUxNC0wYzc5YjNjZmQwMzN8MjAxOS0wNS0xMlQwNzowMDowMC4wMDBafE1PUk5JTkc=",
task_schedule_id: "f256baea-c812-4cec-9514-0c79b3cfd033",
task_schedule_note: "Please assist me to brush my teeth",
timestamp: "2019-05-12T07:23:12.789Z",
visit_id: "5cd753f0-8b66-f8a8-4591-3f78ca3f9c45",
},
payload: {
care_recipient_id: "df50cac5-293c-490d-a06c-ee26796f850d",
caregiver_id: "5c9090ab-7d5e-4a72-8bf7-197190ad4c98",
event_type: "task_completed",
id: "0099ecb2-07bb-4b93-bd56-be485d62f22c",
task_definition_description: "Ensure home is clean and tidy",
task_definition_id: "9ac88364-79c5-4f1d-9767-5e65f16a0711",
task_instance_id:
"dHw2ZGRhZGVkMC1lZjk0LTQ1N2ItYjViMi01NDVhM2JkM2Q0YzF8MjAxOS0wNS0wM1QwNzowMDowMC4wMDBafE1PUk5JTkc=",
task_schedule_id: "6ddaded0-ef94-457b-b5b2-545a3bd3d4c1",
task_schedule_note: "Empty the bins if required.",
timestamp: "2019-05-03T07:24:10.276Z",
visit_id: "5ccb7670-8b66-f8a8-48ca-1c06125a9c4c",
},
},
],
};
I tried to do this
const {
data: [
{
payload: { event_type, task_definition_description, timestamp },
},
],
} = events;
console.log(event_type);
I got an error, I'm probably using the wrong syntax. Does anyone have a better solution please.

How to filter CloudWatch logs from Lambda with a JSON Metric Filter

Using the example straight from documentation, in a lambda function I put:
console.log(
{
"eventType": "UpdateTrail",
"sourceIPAddress": "111.111.111.111",
"arrayKey": [
"value",
"another value"
],
"objectList": [
{
"name": "a",
"id": 1
},
{
"name": "b",
"id": 2
}
],
"SomeObject": null,
"ThisFlag": true
})
I then create a logs metric filter in CloudWatch with a filter pattern as specified in the docs example:
{ $.eventType = "UpdateTrail" }
The filter doesn't generate a metric like the documentation says it should - here's the output:
2017-10-23T13:27:19.320Z 1143e2b0-eea6-4225-88c0-efcd79055f7b { eventType: 'UpdateTrail',
sourceIPAddress: '111.111.111.111',
arrayKey: [ 'value', 'another value' ],
objectList: [ { name: 'a', id: 1 }, { name: 'b', id: 2 } ],
SomeObject: null,
ThisFlag: true }
So as you can see the timestamp and the identifier are prepended to the JSON.
An answer in Amazon Cloudwatch log filtering - JSON syntax says it is because Lambda turns logs into a string. How to parse mixed text and JSON log entries in AWS CloudWatch for Log Metric Filter says much the same. A solution isn't offered in either case. How do you filter CloudWatch logs from Lambda with a JSON Metric Filter?
Look at what the log line actually looks like. If you see something like this, it's not a valid json:
{ eventType: 'UpdateTrail', ... }
What you want is something like this (note the quotation):
{ "eventType": "UpdateTrail", ...}
To get that, try to wrap your object in JSON.stringify(), like this:
console.log(
JSON.stringify(
{
"eventType": "UpdateTrail",
"sourceIPAddress": "111.111.111.111",
"arrayKey": [
"value",
"another value"
],
"objectList": [
{
"name": "a",
"id": 1
},
{
"name": "b",
"id": 2
}
],
"SomeObject": null,
"ThisFlag": true
}
)
)

Iterate through two loops when building the JSON String

I am invoking a restful service to get the available documents on the the server where I am getting the JSON as s response. I am building the JSON String with the JSONBuilder so when invoking the this link
http://localhost:8080/httpConnector/Rest/Documents?Accept=application/json
I am getting the JSON String below:
{
"results": [
{
"result": {
"name": "Test traisy",
"version": "sdvdsv",
"author": "sdvdsv"
}
},
{
"result": {
"name": "Jaspersoft Ultimate guide",
"version": "sdfdsv",
"author": "sdvdsv"
}
},
{
"result": {
"name": "Dohrn",
"version": "12.19.00",
"author": "sdfdsf"
}
}
]
}
Code
String accept = getValue("Accept");
accept = "application/xml";
if ("application/xml".equals(accept)){
builder=new groovy.xml.MarkupBuilder(writer);
}else{
builder=new groovy.json.JsonBuilder();
}
builder{
results foaList.collect{
[
//Here I want to loop through the otaList to do something like that "ota.getName(), foa.getFlexiObject().getByString(ota.getName())"
result: [
name: it.getFlexiObject().getByString("name"),
version: it.getFlexiObject().getByString("version"),
author: it.getFlexiObject().getByString("author")
]
]
}
}
Now I want to add the properties programatically. Therefore I have to loop through the otaList to do something like that
builder.'results'() {
for(FlexiObjectAttachment foa: foaList){
for(ObjectTypeAttribute ota : otaList){
param.put(ota.getName(), foa.getFlexiObject().getByString(ota.getName()));
}
result(param);
}
}
this version just works for the xml respose.
What you can try is to do the combination of foa and ota directly in your collect call.
That way your initially created dict would have the correct structure.
Something like the example below
def foaList = [1, 2, 3, 4]
def otaList = ['A', 'B', 'C']
foaList.collect { foa ->
result = [name: "Name$foa", version: "v$foa", author: "Author$foa"]
otaList.each { ota -> result[ota] = "$ota$foa" }
[ result: result ]
}

Kendo ui grid datasource for nested json

Lets say i had a json format like this
$(document).ready(function ()
{
$('#grid').kendoGrid(
{
scrollable: false,
dataSource: {data: [{ test: 1, data: [ { "TestHeader": "This is some test data"} ] }]},
columns: [ { field: 'TestHeader' } ]
});
});
how do i get the testHeader field to display on kendoui grid?
if the json data is like this
{ test: 1, data: [ { "TestHeader": "This is some test data"} ] }
it would work, but not if it is nested like this
{data: [{ test: 1, data: [ { "TestHeader": "This is some test data"} ] }]}
I can't control what server return, so i can't change the return json, so how can i get this done?
I got it done already, using schema: parse on datasource
found it at here How can I use nested Json to populate Kendo UI grid?

extJS: reading a nested JSON

I have a pretty nested JSON coming from a ldap_search() call. I would like to use this information to populate an ExtJS ComboBox, but I am facing some troubles with the reader. Apparently, I am not able to read the information that I need in the ComboBox, that is the mail address of the people, the uid and the cn
I think the whole problem lies in the store. I was trying the following code:
var store= new Ext.data.JsonStore({
url:'search.php',
root: '',
totalProperty: 'count',
fields: [
{name:'cn', type: 'string', mapping:'cn.0'},
{name:'mail', type: 'string', mapping:'mail.0'},
{name:'uid', type: 'string', mapping:'uid.0'}
]
});
but FireBug told me missing ; before statement return obj.cn.0 in ext-all.js (line 7). I tried with another, easier JSON array and it works, that is why I really think the problem lies in this part of code, especially in the mapping.
an example of JSON returned by search.php is:
{
"count": 2,
"0": {
"mail": {
"count": 1,
"0": "Mail address not registered."
},
"0": "mail",
"uid": {
"count": 1,
"0": "name0.surname0#domain.com"
},
"1": "uid",
"cn": {
"count": 1,
"0": "Surname0 Name0"
},
"2": "cn",
"count": 3,
"dn": "cn=Surname0 Name0,ou=personal,dc=domain,dc=com"
},
"1": {
"mail": {
"count": 1,
"0": "name1.surname1#domain.com"
},
"0": "mail",
"uid": {
"count": 1,
"0": "name1.surname1"
},
"1": "uid",
"cn": {
"count": 1,
"0": "Surname 1 Name 1"
},
"2": "cn",
"count": 3,
"dn": "cn=Surname1 Name1,ou=personal,dc=domain,dc=com"
}
}
Thanks for your time.
Yep, that JSON structure is not going to work straight away with standard ExtJS JSONReader. Take a look at this example taken from the ExtJS API documentation on how the JSON should look like.
{
results: 2000, // Reader's configured totalProperty
rows: [ // Reader's configured root
// record data objects:
{ id: 1, firstname: 'Bill', occupation: 'Gardener' },
{ id: 2, firstname: 'Ben' , occupation: 'Horticulturalist' },
...
]
}
Also, the root config option is required, you cannot leave it empty. In the above example your root would be "rows".
You are probably going to need to parse that JSON of yours into a simpler format at first, before feeding it to the JSONReader.
I was looking to do the same thing, but have one of the nested items be a field in my chart. This post kept coming up, so I thought it might be helpful to see what I did to solve the chart issue. The key to solving it is knowing that the label config exists: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.chart.Label. Using that you can override the default render of what you pass in. In this example the field is "key" (Not shown here, but my model is using the default type for 'key' (ie., not string)). The key object gets passed to renderer. Using function(t), I can now access that object like javascript and pass back the name under the object.
json
key : {
wholePath : "c:/.../fileName.txt",
fileName : "fileName.txt",
}
code:
axes: [
{
title: 'Values',
type: 'Numeric',
position: 'left',
fields: ['value'],
minimum: 0,
maximum: 100,
minorTickSteps: 1
},
{
title: 'File Name',
type: 'Category',
position: 'bottom',
fields: ['key'],
label: {
renderer: function(t) {
var fileName = t.name;
return fileName;
}
}
}