How can I map an object with index signature? - json

I'm about to write an app in angular. It receives an answer from an api. Inside this answer is an array indexed with strings (index signature). How can I map this array into a regular array?
The api looks like this
{
"Information": {
"Created": "2019-04-25",
"Version": "1.2"
},
"Files": {
"2019-04-26": {
'name': 'file1',
'size': 5,
},
"2019-04-25": {
'name': 'file2',
'size': 3,
},
...
}
}
And i want to map it an object that looks like this
export class Model {
'Information': {
'Created': string,
'Version': string,
};
'Files': [{
'date': Date,
'name': string,
'size': number,
}];
}
Here I would like to map the answer
getdata(url): void {
this.http.get<>(url).subscribe(data => {
// code
}
);
}

I haven't tested any of this, but, in summary, the for loop retrives all of the keys of the object data.File and the you can access this object through that key.
getdata(url): void {
this.http.get<>(url).subscribe((response: any) => {
const model: Model = new Model();
model.Files = [];
if (response.Information) {
const information: any = response.Information;
if (information.Created && information.Version) {
model.Information = {
'Created': information.Created,
'Version': information.Version
};
}
}
for (const date in data) {
if (data.File.hasOwnProperty(date)) {
const file: any = data.File[date];
model.Files.push({
'date': date,
'name': file.name,
'size': file.size
});
}
}
});
}

Object.keys(o.Files)
.map(function(k ) {
return {date: k, name: o.Files[k].name, size: o.Files[k].size}
});

It should probably look like this:
data: Array<Data>;
getData() {
this.http.get(`url`).subscribe((data) => {
this.data = data.map(item => {
const output = {};
output.information = item.information;
output.files = Object.keys(item.files).map(key => {
return {
date: new Date(key),
name: item.files[key].name,
size: item.files[key].size
};
});
return output;
});
});
}

Related

TypeScript: find values of certain keys in JSON

I have a JSON that contains a lot of data, here's an example of it:
{
"type":"doc",
"content":[
{
"type":"paragraph",
"content":[
{
"text":"this is a simple page, about a simple umbrella.",
"type":"text"
}
]
},
{
"type":"paragraph",
"content":[
{
"text":"you can use this text to find the umbrella page.",
"type":"text"
}
]
},
{
"type":"paragraph",
"content":[
{
"text":"do you like it?",
"type":"text"
}
]
}
}
I want to extract the value of text key, no matter where the key is located. I'm trying to go over the keys using Object.keys but it only returns the top-level keys:
for (let x of Object.keys(someJson)) {
console.log(x);
}
How can I find all the values of text in this JSON, no matter where in the JSON it is?
You can use JSON.stringify trick, you can intercept all keys from it
function find(obj: object, key: string) {
const ret: any[] = [];
JSON.stringify(obj, (_, nested) => {
if (nested && nested[key]) {
ret.push(nested[key]);
}
return nested;
});
return ret;
};
...
const o = {
key: '123',
a: {
key: 'hello',
b: [
{
c: {
key: 123,
},
},
],
},
};
it('123', () => {
console.log(JSON.stringify(find(o, 'key'))); // ["123","hello",123]
});
if you want for generic JSON just call this function and pass your object :
function printText(obj){
if(Array.isArray(obj)){
for(const o of obj){
printText(o);
}
}else if(typeof obj === "object"){
if (obj){
for(const o of Object.keys(obj)){
if(o==="text"){
console.log(obj.text);
}else{
printText(obj[o]);
}
}
}
}
}

Invalid JSON Payload with Sheets.Spreadsheets.BatchUpdate

Trying to work with Sheets.Spreadsheets.Get and Sheets.Spreadsheets.Batchupdate. I'm trying to get pull formatting from one spreadsheet and paste that formatting to another. This is simply a proof of concept for further application. I get a JSON payload error with the following code and can't see to figure out how to format it to insert the Array.
function Test() {
//sheets[].data[].rowData[].values[].cellData.effectiveFormat.backgroundColor
var TestArray = Sheets.Spreadsheets.get("1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg", {
ranges:"Awesome!A1:C3",
fields:"sheets(data(rowData(values(effectiveFormat.backgroundColor))))"
});
var spreadsheetId = "1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg";
var result = Sheets.Spreadsheets.batchUpdate({
requests: [{
updateCells: {
rows: [{
values: [{
userEnteredValue: {
stringValue: 'Test String'
}, userEnteredFormat: {
backgroundColor: TestArray
}
}]
}],//rows
fields: 'userEnteredValue.stringValue,userEnteredFormat.backgroundColor',
start: {
sheetId: 1616717220,
rowIndex: 0,
columnIndex: 0
}
}//update cell
}]//requests
}, spreadsheetId)
} ```
**EDIT:**
Rebuilt function copying both Text and Background colors.
function myFunction() {
var TestArray = Sheets.Spreadsheets.get("1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg", {
ranges:"Awesome!A1:C3",
fields:"sheets(data(rowData(values(effectiveFormat.backgroundColor))))"
});
var backgroundColors = TestArray["sheets"][0]["data"][0]["rowData"]
.map(row => row["values"]
.map(value => value["effectiveFormat"]["backgroundColor"]));
var TotalText = Sheets.Spreadsheets.Values.get("1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg", "Awesome!A1:C3").values;
//Map Text
var textrows = TotalText.map(rowText => {
return {
values: rowText.map(cellText => {
return {
userEnteredValue: {
stringValue: cellText
}
}
})
}
})
//Map Background Colors
var colorrows = backgroundColors.map(rowColors => {
return {
values: rowColors.map(cellColor => {
return {
userEnteredFormat: {
backgroundColor: cellColor
}
}
})
}
})
var spreadsheetId = "1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg";
var result = Sheets.Spreadsheets.batchUpdate({
requests: [{
updateCells: {
rows: textrows,
fields: 'userEnteredValue.stringValue',
start: {
sheetId: 1616717220,
rowIndex: 0,
columnIndex: 0
}
}//update cell
},{
updateCells: {
rows: colorrows,
fields: 'userEnteredFormat.backgroundColor',
start: {
sheetId: 1616717220,
rowIndex: 0,
columnIndex: 0
}
}
}]
}, spreadsheetId)
}
Edit #2:
function myFunctionOneRequest() {
var TestArray = Sheets.Spreadsheets.get("1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg", {
ranges:"Awesome!A1:C3",
fields:"sheets(data(rowData(values(effectiveFormat.backgroundColor))))"
});
var backgroundColors = TestArray["sheets"][0]["data"][0]["rowData"]
.map(row => row["values"]
.map(value => value["effectiveFormat"]["backgroundColor"]));
var TotalText = Sheets.Spreadsheets.Values.get("1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg", "Awesome!A1:C3").values;
//Map Text
var textrows = TotalText.map((rowText,i) => {
return {
values: rowText.map((cellText,j) => {
return {
userEnteredValue: {
stringValue: cellText
}
}
})
}
})
//Map Background Colors
var colorrows = backgroundColors.map((rowColors,k) => {
return {
values: rowColors.map((cellColor,l) => {
return {
userEnteredFormat: {
backgroundColor: cellColor
}
}
})
}
})
var spreadsheetId = "1eAq-RbtrCSMRPZ0p7XIpG3vd29yL-3SQ3D3JGyiUhKg";
var result = Sheets.Spreadsheets.batchUpdate({
requests: [{
updateCells: {
rows: textrows,
fields: 'userEnteredValue.stringValue',
start: {
sheetId: 1616717220,
rowIndex: 0,
columnIndex: 0
}
}//update cell
}]
}, spreadsheetId)
}
Issue:
You are supplying at Spreadsheet resource (TestArray, returned by spreadsheets.get) where you should provide a color. Hence, you are getting an invalid JSON payload error.
This is because the fields parameter will filter which nested fields will be populated in the response of your first call, but these nested fields will still be nested on your JSON, and you'll have to access them by specifying the corresponding parent properties.
Solution:
The response to your first call is something like:
{
"sheets": [
{
"data": [
{
"rowData": [
{
"values": [
{
"effectiveFormat": {
"backgroundColor": {
"red": 1,
"green": 1,
"blue": 1
}
}
},
// Other cells in row
]
},
// Other rows in the requested range
]
} // Only one range is specified, so there's only one GridData element
]
},
// Other sheets
]
}
So, for example, if you want to access the backgroundColor of the first cell of the first row in the requested range, you should do the following:
var backgroundColor = TestArray["sheets"][0]["data"][0]["rowData"][0]
["values"][0]["effectiveFormat"]["backgroundColor"];
Or, alternatively, if you want to retrieve a 2D array of the backgroundColors of all the cells in the requested range, you could do this:
var backgroundColors = TestArray["sheets"][0]["data"][0]["rowData"]
.map(row => row["values"]
.map(value => value["effectiveFormat"]["backgroundColor"]));
If you want to update several cells, you would need to edit the request body accordingly, adding the additional rows and values to the corresponding arrays.
Edit:
For example, if you want the destination cells to have the same background colors as the source, and all of them to have the value Test String, you could build your request body like this:
var rows = backgroundColors.map(rowColors => {
return {
values: rowColors.map(cellColor => {
return {
userEnteredValue: {
stringValue: 'Test String'
},
userEnteredFormat: {
backgroundColor: cellColor
}
}
})
}
})
var result = Sheets.Spreadsheets.batchUpdate({
requests: [{
updateCells: {
rows: rows,
fields: 'userEnteredValue.stringValue,userEnteredFormat.backgroundColor',
start: {
sheetId: 1616717220,
rowIndex: 0,
columnIndex: 0
}
}//update cell
}]//requests
}, spreadsheetId)
If each cell should have different string values, you should store those in a 2D array, and provide them inside the map methods, instead of Test String, specifying the corresponding indexes (provided as an optional parameter in each map).
Edit 2:
In order to update both values and background colors with the same request, you can just iterate through one of them with map, and use the corresponding index parameters (they are optional parameters of the map method, called i and j in the sample below) to access the different values of the other one.
For example, if backgroundColors and strings the 2D arrays which you want to use to build rows, you can do this:
var backgroundColors = [["2D array with colors"]];
var strings = [["2D array with strings"]];
var rows = backgroundColors.map((rowColors,i) => {
return {
values: rowColors.map((cellColor,j) => {
return {
userEnteredValue: {
stringValue: strings[i][j]
},
userEnteredFormat: {
backgroundColor: cellColor
}
}
});
}
});

Failed to construct 'PaymentRequest': Iterator getter is not callable

I'm following a tutorial about new PaymentRequest API but I get an error:
Uncaught TypeError: Failed to construct 'PaymentRequest': Iterator
getter is not callable.
at startPayment ((index):45)
function startPayment(){
if (!window.PaymentRequest) {
// PaymentRequest API is not available. Forwarding to
// legacy form based experience.
location.href = '/checkout';
return;
}
const methods = {
supportedMethods: "basic-card",
data: {
supportedNetworks: [
'visa', 'mastercard', 'amex', 'discover',
'diners', 'jcb', 'unionpay'
]
},
}
const details = {
total: {
label: 'Tyle musisz zabulić',
amount: { currency: 'PLN', value : '22.15' }
},
displayItems: [{
label: 'Narkotyki',
amount: { currency: 'PLN', value: '22.15' }
}],
}
const options = {
requestShipping: true,
requestPayerEmail: true,
requestPayerPhone: true,
requestPayerName: true,
shippingType: 'delivery'
};
const request = new PaymentRequest(methods, details, options) // this line fails
request.show().then(response => {
// [process payment]
// send to a PSP etc.
response.complete('success');
});
}
What does it mean and how can I fix it?
MacOS Chrome version: 72.0.3626.121 64bit
payment methods should be an array:
const methods = [
{
supportedMethods: "basic-card",
data: {
supportedNetworks: [
'visa', 'mastercard', 'amex', 'discover',
'diners', 'jcb', 'unionpay'
]
},
}
]

Map JSON for Chartjs with Angular 7

Im trying to map JSON Data to show it in a Bar-Chart. The final Array I need has to look like this:[883, 5925, 17119, 27114, 2758].
Actually, the Array I want to use to set the barChartData (dringlichkeitenValues[])seems to be empty. Sorry for my bad coding skills. Can anyone show me how to solve this Problem?
JSON:
[{
"id": 1,
"value": 883
},
{
"id": 2,
"value": 5925
},
{
"id": 3,
"value": 17119
},
{
"id": 4,
"value": 27144
},
{
"id": 5,
"value": 2758
}]
api.service.ts
getDringlichkeiten(): Observable<IDringlichkeit[]> {
return this.http.get<IDringlichkeit[]>(this.ROOT_URL + '/aufenthalte/dringlichkeit');}
dringlichkeit.ts
export interface IDringlichkeit {
id: number;
value: number;
}
bar-chart.component.ts
export class BarChartComponent implements OnInit {
public dringlichkeitValues:number[] = [];
public dringlichkeiten: IDringlichkeit[];
public barChartLabels:String[] = ["1", "2", "3", "4", "5"];
public barChartData:number[] = this.dringlichkeitValues;
public barChartType:string = 'bar';
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.loadData();
this.getDringlichkeitValues();
}
loadData(){
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => this.dringlichkeiten = data);
}
getDringlichkeitValues(){
let dringlichkeitValues:number[]=[];
this.dringlichkeiten.forEach(dringlichkeit=>{
dringlichkeitValues.push(dringlichkeit.value)
this.dringlichkeitValues = dringlichkeitValues;
});
return this.dringlichkeitValues;
}
}
UPDATE:
I updated my component but now my Array is still empty after subscribing to the Observable.
bar-chart.component.ts
chart: Chart;
dringlichkeiten: IDringlichkeit[] = [];
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => {
this.dringlichkeiten = data;
//dringlichkeiten-Array full
console.log(this.dringlichkeiten);
});
//dringlichkeiten-Array empty
console.log(this.dringlichkeiten);
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: this.dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'Dringlichkeiten',
data: this.dringlichkeiten.map(x => x.value),
backgroundColor: ['#FF6384', '#4BC0C0', '#FFCE56', '#E7E9ED', '#36A2EB']
}
]
},
});
}
To get the "values" from your JSON array, you can use:
dringlichkeiten.map(x => x.value)
This will get you an array you require, i.e.:
[883, 5925, 17119, 27114, 2758]
You can then pass this array to chartJS for it to render you a chart like so:
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'My Bar Chart',
data: dringlichkeiten.map(x => x.value),
backgroundColor: ['red', 'green', 'yellow', 'blue', 'orange']
}
]
},
});
Take a look at this simplified working SlackBlitz example.
Hope this helps!

Single JSON argument in mutation

Below I'm trying to set a mutation example with one object-arg credentials. I had this working previously then all the sudden it stopped working failing on the JSON part. Why can't I send json through credentials?
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLInputObjectType,
GraphQLNonNull,
graphql
} from 'graphql'
let requestType = new GraphQLInputObjectType({
name: 'Request',
fields: {
name: {type: GraphQLString},
}
})
let responseType = new GraphQLObjectType({
name: 'Response',
fields: {
name: {type: GraphQLString},
age: {type: GraphQLInt}
}
})
let schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
author: {
type: GraphQLString,
resolve: (source, args, context, info) => {
return 'Thomas Reggi'
}
}
}
}),
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: {
example: {
type: responseType,
args: {
credentials: {
name: 'credentials',
type: requestType
}
},
resolve: (source, args, context, info) => {
return {
'name': 'Thomas Reggi',
'age': 26
}
}
}
}
})
})
let credentials = { name: "Thomas Reggi" }
let requestString = `
mutation {
example(credentials: ${JSON.stringify(credentials)}) {
name,
age
}
}`
graphql(schema, requestString).then(result => {
console.log(result)
})
Here's the error:
{ errors:
[ Syntax Error GraphQL request (3:25) Expected Name, found String "name: "
2: mutation {
3: example(credentials: {"name":"Thomas Reggi"}) {
^
4: name,
] }
Where does the reference to Name come from? Why is this throwing an error?
Just found out the hard way. You can't have {"name": "Thomas Reggi"} because name is in quotes.
This query works.
mutation {
example(credentials: {name: "Thomas Reggi"}) {
name,
age
}
}