Mapping complex Observable json to class or interface - json

I have an API I am consuming with a service in Angular 8.0.0. I cannot seem to understand how to map the json returned to an object.
All of the examples I have seen have been simple examples of an array of clearly defined and easily traversed json. The json set I am getting back is quite complex.
Ideally, since there is a lot of repeated patterns in there, I would make a class with other classes as members of the class.
Is there a way to just transform the returned observable json into the associated dictionary of dictionaries?
If I were to template this, I'm struggling with the fact that I get a dictionary back and not an array.
Here is the service design pattern that I am following. Since this design pattern transforms a simple json payload into a simple interface, it's not complex enough for me to try and transpose to my use-case. I have doubt on the ability to transform this complex dataset to an interface or class.
getTeams() {
return this.http.get<ITeam[]>(this._url).pipe(
retry(1), catchError(error => {
return throwError(error.message || 'Undefined Server Error');
}));
}
Here is my sample dataset similar to what I am trying to consume in my angular component via my service:
{
"stlouis_teams": {
"blues": {
"version": "12.0-57.24",
"image": "stl_team_photo.jpg",
"image_md5": "fffffc429735ffff4d6c716c113f3ffff",
"stadium_phones": {
"landlines": [
"210-555-1212",
"309-555-1212"
],
"cells": [
"312-555-1212",
"502-555-1212"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
},
"jv_blues": {
"version": "1.0-0.0",
"image": "jv_stl_team_photo.jpg",
"image_md5": "9999c42973599994d6c716c113f39999",
"stadium_phones": {
"landlines": [
"210-555-1111",
"309-555-1111"
],
"cells": [
"312-555-1111",
"502-555-1111"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
}
},
"chicago_teams": {
"blackhawks": {
"version": "11.33",
"image": "chi_team_photo.jpg",
"image_md5": "00000c42973500004d6c716c113f30000",
"stadium_phones": {
"landlines": [
"702-555-1212",
"412-555-1212"
],
"cells": [
"217-555-1212",
"904-555-1212"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
},
"minor_blackhawks": {
"version": "1002.2",
"image": "minor_chi_team_photo.jpg",
"image_md5": "ccccccc42973500004d6c716c113fccccc",
"stadium_phones": {
"landlines": [
"702-555-2222",
"412-555-2222"
],
"cells": [
"217-555-2222",
"904-555-2222"
]
},
"coaching_staff": {
"coach": {
"image": "bill_brasky.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_brasky.jpg",
"http://example.com/bill_brasky.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_brasky.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_brasky.jpg"
]
},
"image_md5": "4444444d0a2c1cad1437570f0e4444444"
},
"asst_coach": {
"image": "bill_billy.jpg",
"image_locations": {
"http": [
"http://example.com/images/bill_billy.jpg",
"http://example.com/bill_billy.jpg"
],
"ftp": [
"ftp://example.com/public/images/bill_billy.jpg",
"ftps://example.com/secure/aoe124/public/images/bill_billy.jpg"
]
},
"image_md5": "333333333d0a2c1cad1437570f0e33333333"
}
}
}
}
}

Related

Getting all subitems from all documents with a Couchbase map/reduce view

I have Couchbase documents with structure like this:
{
"subscriberIds": [
{
"type": "END_USER",
"identity": "00000000223"
}
],
"userDataId": "SUB-00000000223",
"status": "ACTIVATED",
"subscriptions": [
{
"id": "Something1",
"attributes": [
{
"value": "Active",
"name": "Status"
}
],
"priority": "1",
"subscriptionStartDate": somedate,
"productShortName": "Something1"
},
{
"id": "Something2",
"attributes": [
{
"value": "Active",
"name": "Status"
}
],
"priority": "1",
"subscriptionStartDate": somedate,
"productShortName": "Something2"
}
],
}
And I'm trying to write a view to get all the 'subscriptions' from all documents in bucket as:
{"total_rows":900,"rows":[
{"id":"Something1","key":null,"value":"00000000223"},
{"id":"Something2","key":null,"value":"00000000223"},
...
but, I can't get nested item from doc
function (doc, meta) {
for (var i in doc.subscriptions) {
emit(doc.subscriptions.id, doc.id);
}
}
I know this is possible, but apparently I do not fully understand the concept of views.
for (var i in doc.subscriptions) {
emit(doc.subscriptions[i].id, doc.id);
}

Merge the JSON data with same value in typescript

I have a JSON Data that I am getting from URL. I want to merge the data which has same Value Below is the sample data. I have searched through the Internet,but i didn't got the solution. All i found is for same Keys.
[ {
"banana": [
{
"color": yellow,
"size": "small"
},
{
"size": "medium"
},
{
"size": "large"
}
],
"process_name": "fruits"},{
"carnivores": [
{
"name": "lion"
},
{
"name": "tiger"
},
{
"name": "chetah"
},
{
"name": "dianosaur"
}
],
"process_name": "animal"}, {
"apple": [
{
"color": red,
"size": "large"
}
],
"process_name": "fruits"}]
And I want to merge the data of "process_name" :"fruits" into one array as below and the result should be
[{
"banana": [
{
"color": yellow,
"size": "small"
},
{
"size": "medium"
},
{
"size": "large"
}
],
"apple": [
{
"color": red,
"size": "large"
}
],
"process_name": "fruits" }, {
"carnivores": [
{
"name": "lion"
},
{
"name": "tiger"
},
{
"name": "chetah"
},
{
"name": "dianosaur"
}
],
"process_name": "animal"}]
can anyone help on this?
Just some snippet to start:
// data definition
const json_before = [ {
"banana": [
{
"color": "yellow",
"size": "small"
},
{
"size": "medium"
},
{
"size": "large"
}
],
"process_name": "fruits"},
{
"carnivores": [
{
"name": "lion"
},
{
"name": "tiger"
},
{
"name": "chetah"
},
{
"name": "dianosaur"
}
],
"process_name": "animal"},
{
"apple": [
{
"color": "red",
"size": "large"
}
],
"process_name": "fruits"
}];
// processing
const json_after = json_before.reduce((arr, next) => {
const exist = arr.find(el => el.process_name === next.process_name);
if (exist) Object.assign(exist, next);
else arr.push(next);
return arr;
}, []);
// check
console.log(json_after);
The main idea is to use reduce for array traversing. To shorten the processing code, I've used Object.assign to modify previuosly added element, although in real code it's better to use Object.keys and manually check whether the properties of the previous object aren't overwritten.
Note that this is mutating the source data (check by adding console.log(json_before)). Again, if you don't want this, you should clone each element yourself, without direct object assignment.

How to send carousel through API.AI?

My bot wants to send a carousel to Google Assistant through API.AI. My understanding is, I need to enclose it inside data -> google, such as:
{
"data": {
"google": {
"expectUserResponse": true,
"isSsml": false,
"expectedInputs": [
{
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hello World"
}
}
]
}
},
"possibleIntents": [
{
"intent": "actions.intent.OPTION",
"inputValueData": {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
"carouselSelect": {
"items": [
{
"optionInfo": {"key": "FOO", "synonyms": ["foo"]},
"title": "Foo",
"image": {"url": "http://example.com/", "accessibilityText": "Foo"}
},
{
"optionInfo": {"key": "BAR", "synonyms": ["bar"]},
"title": "Bar",
"image": {"url": "http://example.com/", "accessibilityText": "Bar"}
}
]
}
}
}
]
}
]
}
}
}
But it doesn't work. What is the proper format?
If you are testing this through the Simulator, there should have been a validation error that appeared that would give you at least a little guidance about what is missing. If you didn't even get that, there may be a problem with the other parts besides the data.google object such that api.ai had problems with it.
There are a number of things that, at a glance, could be the problem. You can't just stick a conversation webhook response in the api.ai response. See https://developers.google.com/actions/apiai/webhook#response for the documentation, but here are a few things that I see that could be issues
The expectedInputs property shouldn't be there.
Your data.google.expectedInputs.possibleIntents property should be at data.google.systemIntent
You still need to provide the api.ai fields, such as a basic speech property
The data.google.expectedInputs.inputPrompt.richInitialPrompt would be at data.google.richResponse
Here is some JSON that works for me:
{
"speech": "Hello",
"contextOut": [
{
"name": "_actions_on_google_",
"lifespan": 100,
"parameters": {}
}
],
"data": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hello"
}
}
],
"suggestions": []
},
"systemIntent": {
"intent": "actions.intent.OPTION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
"carouselSelect": {
"items": [
{
"title": "Foo",
"image": {
"url": "http://example.com/foo.jpg",
"accessibilityText": "Foo title"
},
"optionInfo": {
"key": "foo-key",
"synonyms": [
"foo-alt-1",
"foo-alt-2"
]
}
},
{
"title": "Bar",
"image": {
"url": "http://example.com/bar.jpg",
"accessibilityText": "Bar title"
},
"optionInfo": {
"key": "bar-key",
"synonyms": [
"bar-alt-1",
"bar-alt-2"
]
}
}
]
}
}
}
}
}
}

Get nested Childrens in JSON using Angular2

I'm working on json Data with inner childrens. i need to get all the name's in the json.
json data
this.res = [
{
"children": [
{
"children": [
{
"children": [],
"name": "P Sub Child 3",
},
{
"children": [
{
"children":[],
"name" : "data"
}
],
"name": "PSubChild2",
}
],
"name": "PChild1",
},
{
"children": [
{
"children": [],
"name": "PSubChild3",
}
],
"name": "PChild2",
}
],
"name": "Parent1",
},
{
"children": [],
"name": "Parent2",
}
];
in my application names of every child has to store in the variables using angular2.
Data is dynamic changes as per the user in my application
From what I understand you want to just get the value of the name property down the hierarchical data you have then as most here suggested you have to use recursion to get to the name property. With Rxjs it becomes a bit easier to do like following:
Observable.from(this.res)
.expand(d => d.children.length > 0 ? Observable.from(d.children) : Observable.empty())
.subscribe(d => console.log(d.name));
I have made a working sample here: https://jsfiddle.net/ibrahimislam/ba17w8xz/1/
Here is a plunkr of a possible implementation
https://plnkr.co/edit/njM1HLx7vuZY9loto2pM?p=preview
Create your own datatype:
export class MyNode {
children:Array<MyNode>;
name:string;
}
and then create a method to recursively loop your parents to get their names and the names of the children
parents:Array<MyNode> = [
{
"children": [
{
"children": [
{
"children": [],
"name": "P Sub Child 3",
},
{
"children": [
{
"children":[],
"name" : "data"
}
],
"name": "PSubChild2",
}
],
"name": "PChild1",
},
{
"children": [
{
"children": [],
"name": "PSubChild3",
}
],
"name": "PChild2",
}
],
"name": "Parent1",
},
{
"children": [],
"name": "Parent2",
}
];
names:Array<string>=[];
getAllNames(){
this.getNameHelper(this.parents);
}
getNameHelper(parents:Array<MyNode>){
for(var p of parents){
if(p.name){
this.names.push(p.name);
}
if(p.children){
this.getNameHelper(p.children);
}
}
}

How to repeat multiple lists inside data weave in mule

The problem i am facing is with repeating multiple lists inside dataweave.
input of the dataweave --> coming in two flow varibles (as below),
var1: [{bkAuthorID=1, bkAuthorName=abc, bookCategory=horror}, {bkAuthorID=2, bkAuthorName=xyz, bookCategory=horror}, {bkAuthorID=1, bkAuthorName=abc, bookCategory=comedy}, {bkAuthorID=2, bkAuthorName=xyz, bookCategory=Fantacy}}]
var2: [{bkAuthorID=1, bkName=gjh, bkDescription=kjh},{bkAuthorID=1, bkName=sfs, bkDescription=kjh},{bkAuthorID=2, bkName=gjh, bkDescription=kjh},{bkAuthorID=2, bkName=gjh, bkDescription=kjh}]
output in dataweave --> desired json structue with three lists is like below.
{
"books": [
{
"bookAuthor": "abc",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
},
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
},
{
"bookCategory": "comedy",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
}
]
},
{
"bookAuthor": "xyz",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "xyz",
"bookDescription":"lmn"
}
]
}
]
}
]
}
Can anyone help on this dataweave mapping for this requirement.
#Manik, can you please help me out.
I am able to establish relation between var1 and var2 using bkAuthorID.
But, there has to be one more relation to tell which book in var2 belongs to which category. Hence, in the below output, each category will have list of all the books written by that author. Anyways, all you need to do is just add one more filter condition in 'listOfBooks' line.
Dataweave code:
%dw 1.0
%output application/json
---
{
books:( flowVars.var1 groupBy $.bkAuthorName map using (authorId=$.bkAuthorID[0]) {
bookAuthor:$[0].bkAuthorName,
bookCategorys: $ groupBy $.bookCategory map {
bookCategory:$.bookCategory[0],
listOfBooks: flowVars.var2[?($.bkAuthorID == authorId)] map {
bookName:$.bkName,
bookDescription:$.bkDescription
}
}
})
}
Output:
{
"books": [
{
"bookAuthor": "abc",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "sfs",
"bookDescription": "kjh"
}
]
},
{
"bookCategory": "comedy",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "sfs",
"bookDescription": "kjh"
}
]
}
]
},
{
"bookAuthor": "xyz",
"bookCategorys": [
{
"bookCategory": "horror",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "gjh",
"bookDescription": "kjh"
}
]
},
{
"bookCategory": "Fantacy",
"listOfBooks": [
{
"bookName": "gjh",
"bookDescription": "kjh"
},
{
"bookName": "gjh",
"bookDescription": "kjh"
}
]
}
]
}
]
}