I have following JSON and I try to map it to Angular 7 object with no result:
[
{
"id": "123456",
"general": {
"number": "123",
"name": "my name 1",
"description": "My description with <li> html tags </li>"
},
"option1": {
"name": "option1 name"
},
"option2": {
"suboption2": {
"name": "suboption2 name"
}
}
},
{
"id": "789123",
"general": {
"number": "456",
"name": "my name 2",
"description": "My description with <li> html tags </li>"
},
"option1": {
"name": "option2 name"
},
"option2": {
"suboption2": {
"description": "My description with <li> html tags </li>"
}
}
}
]
I tried to create MyClass instance with fields with the same name as in the JSON file and cast that JSON file to this class but with no success.
I would create a mapper (service) that receives your DTOs (data transfer object, essentially your JSON response) as parameter and output your MyClass object.
In your map function (in your service), you would iterate over your array of DTOs and create a new instance of MyClass for each DTO and then return your array of MyClass
map(myClassDtos:MyClassDTO[]):MyClass[]{
return myClassDtos.map(dto=>{
return new MyClass(...);
});
}
First I would change your JSON structure for something like this, it's more structured:
[
{
"id": "123456",
"general": {
"number": "123",
"name": "my name 1",
"description": "My description with <li> html tags </li>"
},
"options": [
{
"name": "option1 name"
},
{
"name": "option2 name",
"suboptions": [
{
"name": "suboption1 name"
}
]
}
]
},
{
"id": "789123",
"general": {
"number": "456",
"name": "my name 2",
"description": "My description with <li> html tags </li>"
},
"options": [
{
"name": "option1 name"
},
{
"name": "option2 name",
"suboptions": [
{
"name": "suboption1 name"
},
{
"name": "suboption2 name"
}
]
},
{
"name": "option3 name",
"suboptions": [
{
"name": "suboption1 name"
},
{
"name": "suboption2 name"
}
]
}
]
}
]
After that write model interfaces to model all your JSON array items:
main-element.ts
import { General } from './general';
import { Options } from './options';
export interface Element {
id?: number;
general?: General;
options?: Options[];
}
generl.ts
export interface General {
number?: number;
name?: string;
description?: number;
}
import { Suboptions } from './suboptions';
options.ts
export interface Options {
name?: string;
suboptions?: Suboptions[];
}
suboptions.ts
export interface Suboptions {
name?: string;
}
And finally, where you want to map, simply do this:
import { Component } from '#angular/core';
import { Element } from './models/main-element';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private elementsList: Element[] = [];
constructor(){
}
mapJSON(){
this.elementsList = this.someJsonString; //Here you need to insert your json string data
console.log(this.elementsList);
}
}
As result you will get this, if you print in console the elementsList object that's defined on the last part of code.
Related
This is my JSON file.
{mood:
[ {
"id":"1",
"text": "Annoyed",
"cols": 1,
"rows": 2,
"color": "lightgreen",
"route":"/angry",
"musics": [
{
"id": "0",
"name": "English- Heaven's Peace",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EgleopO8DiEdsNKgqYZZSEKF",
"descpription": "Tunes that soothe your pained soul",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "1",
"name": "English- Hell's Fire",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EgmZitRQf1X1iYwWW_nUF44L",
"descpription": "Beats that match the ones of your heart",
"reviews": [
{
"name": "abc",
"rating": 3.5,
"review": "energetic",
"date": ""
}
]
},
{
"id": "2",
"name": "Hindi",
"image": "images/music.png",
"link": "",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "3",
"name": "Punjabi",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3Egnntch2thUO55YqPQgo4Qh7",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 4,
"review": "energetic",
"date": ""
}
]
},
{
"id": "4",
"name": "Mix and Match",
"image": "images/music.png",
"link": "https://www.youtube.com/playlist?list=PLPfXrbtn3EglN5LVTETqH3ipRLfXmY6MB",
"descpription": "",
"reviews": [
{
"name": "abc",
"rating": 5,
"review": "energetic",
"date": ""
}
]
}
]
} ]
}
I have created angular services in a file name mood.services.ts
import { Injectable } from '#angular/core';
import { Mood } from '../shared/mood';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { map, catchError } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { baseURL } from '../shared/baseurl';
import { ProcessHTTPMsgService } from './process-httpmsg.service';
#Injectable({
providedIn: 'root'
})
export class MoodService {
constructor(private http: HttpClient,
private processHTTPMsgService: ProcessHTTPMsgService) { }
getMoods(): Observable<Mood[]> {
return this.http.get<Mood[]>(baseURL + 'moods')
.pipe(catchError(this.processHTTPMsgService.handleError));
}
getMood(id: number): Observable<Mood> {
return this.http.get<Mood>(baseURL+'moods/'+id)
.pipe(catchError(this.processHTTPMsgService.handleError));
}
getMoodIds(): Observable<number[] | any> {
return this.getMoods().pipe(map(moods => moods.map(mood => mood.id)))
.pipe(catchError(error => error));
}
getMusicIds(): Observable<number[] | any> {
return this.getMoods().pipe(map(musics => musics.map(music => music.id)))
}
}
And this is my musicdetail.component.ts file which will fetch the data of the particular music that is chosen.
import { Component, OnInit, Inject } from '#angular/core';
import { Mood } from '../shared/mood';
import { Music } from '../shared/music';
import { Review } from '../shared/review';
import { MoodService } from '../services/mood.service';
import { Params, ActivatedRoute } from '#angular/router';
import { Location } from '#angular/common';
import { switchMap } from 'rxjs/operators';
#Component({
selector: 'app-musicdetail',
templateUrl: './musicdetail.component.html',
styleUrls: ['./musicdetail.component.scss']
})
export class MusicdetailComponent implements OnInit {
mood : Mood;
music: Music;
musicIds: string;
errMess: string;
prev : string;
next : string;
review: Review;
constructor(private moodservice: MoodService,
private route: ActivatedRoute,
private location: Location,
#Inject('BaseURL') private BaseURL) { }
ngOnInit(): void {
this.route.params.pipe(switchMap((params: Params) => {return this.moodservice.getMood(params['id']);
}))
.subscribe(mood => {this.mood = mood;}, errmess => this.errMess = <any>errmess);
}
}
I have passed both mood.id and music.id when clicked in music.component.ts using '[routerLink]="['/musicdetails', mood.id, music.id]"`, on the list of music but I am unable to make logic to fetch particular music to display all its details. I am able to get mood-id using getMood(id) service but unable to do the same for music inside that mood.
WARNING:
your JSON data is wrong, Either you have missing single quote or double quote or 2nd bracket or third bracket. I don't know what you missed, its a long JSON file .
There is a JSON fixing website ( this one ) . I pasted your JSON and fixed it first.
Now I am writing this answer using correct version of your JSON (you can see it below)
So here it the answer:
The answer is simple - just use filter method to filter a particular property you need
.ts :
let jsonData =
{
"mood":[
{
"id":"1",
"text":"Annoyed",
"cols":1,
"rows":2,
"color":"lightgreen",
"route":"/angry",
"musics":[
{
"id":"0",
"name":"English- Heaven's Peace",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgleopO8DiEdsNKgqYZZSEKF",
"descpription":"Tunes that soothe your pained soul",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"1",
"name":"English- Hell's Fire",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EgmZitRQf1X1iYwWW_nUF44L",
"descpription":"Beats that match the ones of your heart",
"reviews":[
{
"name":"abc",
"rating":3.5,
"review":"energetic",
"date":""
}
]
},
{
"id":"2",
"name":"Hindi",
"image":"images/music.png",
"link":"",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"3",
"name":"Punjabi",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3Egnntch2thUO55YqPQgo4Qh7",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":4,
"review":"energetic",
"date":""
}
]
},
{
"id":"4",
"name":"Mix and Match",
"image":"images/music.png",
"link":"https://www.youtube.com/playlist?list=PLPfXrbtn3EglN5LVTETqH3ipRLfXmY6MB",
"descpription":"",
"reviews":[
{
"name":"abc",
"rating":5,
"review":"energetic",
"date":""
}
]
}
]
}
]
} ;
// music - i can save here
let r = jsonData.mood[0].musics.filter(data => data.id == "2");
// music - or i can console.log it also
// i am comparing with 2 here - compare with your id number
// according to your need
console.log(jsonData.mood[0].musics.filter(data => data.id == "2"));
// in the same way you can search mood also
console.log(jsonData.mood.filter(data=> data.id == "1"));
to get something from parameter of url : follow this
there are multiple ways to get params from url
see this question : stackoverflow
see this blog : digitalocean
I am still learning Vue.js. At the moment I am trying to make a simple filtered list method that pulls the data from a json file in Vue. I think that I am having trouble figuring out the correct syntax.
I just cant seem to get it right. Any help is more than welcome :)
This is Vue file:
<template>
<section>
<ul>
<li v-for="product in rings" :key="product">
{{product.title}}
</li>
</ul>
</section>
</template>
<script>
import data from '#/assets/data.json';
export default {
data() {
return {
products: []
}
},
methods: {
computed: {
rings(){
return this.products.filter(product => product.type == 'Ring')
}
}
}
}
</script>
And this is the Json file:
{ "products": [
{
"title": "Ring 1",
"description": "something",
"type": "Ring",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Halskæde 1",
"description": "something",
"type": "Halskæde",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Armbånd 1",
"description": "something",
"type": "Armbånd",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
},
{
"title": "Ørering 1",
"description": "something",
"type": "Ørering",
"year": "2018",
"image": "...",
"price": "2000,00 kr."
}
]
}
You imported the data but never used anywhere inside the component:
import data from '#/assets/data.json';
// notice the data here is just a variable and it has nothing to do with the
// component's data property
export default {
data () {
return {
products: data.products // init products with imported data
}
},
Or with the destructuring syntax:
import { products } from '#/assets/data.json';
export default {
data () {
return {
products // init products with imported data
}
},
I am working on angular 2 Tabs component.
Currently i am following below Plunker example
Angular 2 Tabs
I need to make Tabs dynamic by reading the Local JSON file.
My JSON
[
{
"id": "1",
"name": "General",
"content": [
{
"header": "Basic Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
},
{
"id": "2",
"name": "Additional info",
"content": [
{
"header": " Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
}
]
Service.ts
export class DashboardService{
private _url: string = "assets/sample.json";
constructor( private _http: Http){}
getRecords(){
return this._http.get(this._url)
.map((response:Response) => response.json())
.catch(this._errorHandler);
}
_errorHandler(error: Response){
console.error(error);
return Observable.throw(error || "Server Error");
}
}
Component.ts
export class DynamicTabsComponent implements OnInit{
records = [];
errorMsg: string;
constructor(private _dashboardService: DashboardService) { }
ngOnInit() {
this._dashboardService.getRecords()
.subscribe(
resGetRecords => this.records = resGetRecords,
resRecordsError => this.errorMsg = resRecordsError
);
}
}
Now how to read it in the component file.
here in tab link, i am expecting is
Additional info
General
Description required with header and label.
Any help would be appreciated.
You do an *ngFor on your json to display the tabs:
<tabs>
<tab *ngFor="let tab of tabs" tabTitle="{{tab.name}}">
<div>{{tab.content[0].header}}</div>
<div>{{tab.content[0].contents[0].label}}</div>
</tab>
</tabs>
You declare your json into the component or import it from outside:
class App {
tabs = [
{
"id": "1",
"name": "General",
"content": [
{
"header": "Basic Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
},
{
"id": "2",
"name": "Additional info",
"content": [
{
"header": " Information",
"contents": [
{
"label": "Report goes here"
}
]
}
]
}
];
}
Working fork of your plunker here
If it's a local JSON file, why are you making http calls ?
To read a JSON file, simply do
let jsonFile = require('relative/path/to/json/file.json')
And it should load your JSON file.
I have tried looking on many sites and browsed through many posts here, but still can't find what I am looking for, or at least could not implement it work. I have an API response where depending on the request parameters it either returns an object with an array of objects (which I am able to deal with), or an object with several objects that contain arrays within them. I was able to get the data from the simple form, but the multi-object containing object is kicking my butt. I am also doing this in Angular 4, just in case that makes a difference. The response is from the holiday api.
Below is the full response with no filtering params, minus a few objects, to not beat a dead horse.
{ "status": 200, "holidays": {
"2016-01-01": [
{
"name": "Durin's Day",
"date": "2016-01-01",
"observed": "2016-01-01",
"public": true
}
],
"2016-02-23": [
{
"name": "Founder's Day",
"date": "2016-02-23",
"observed": "2016-02-23",
"public": true
}
],
"2016-02-29": [
{
"name": "Leap Day",
"date": "2016-02-29",
"observed": "2016-02-29",
"public": false
}
],
"2016-03-20": [
{
"name": "Weasel Stomping Day",
"date": "2016-03-20",
"observed": "2016-03-20",
"public": false
}
],
"2016-04-05": [
{
"name": "First Contact Day",
"date": "2016-04-05",
"observed": "2016-04-05",
"public": false
}
],
"2016-04-06": [
{
"name": "Second Contact Day",
"date": "2016-04-06",
"observed": "2016-04-06",
"public": false
}
],
"2016-05-10": [
{
"name": "Whacking Day",
"date": "2016-05-10",
"observed": "2016-05-10",
"public": false
}
],
"2016-10-31": [
{
"name": "Harry Potter Day",
"date": "2016-10-31",
"observed": "2016-10-31",
"public": false
}
],
"2016-11-24": [
{
"name": "Hogswatch",
"date": "2016-11-24",
"observed": "2016-11-24",
"public": false
}
],
"2016-12-23": [
{
"name": "Festivus",
"date": "2016-12-23",
"observed": "2016-12-23",
"public": true
}
],
"2016-12-25": [
{
"name": "Decemberween",
"date": "2016-12-25",
"observed": "2016-12-25",
"public": false
},
{
"name": "Winter Veil",
"date": "2016-12-25",
"observed": "2016-12-26",
"public": true
}
]
} }
Here is the code used:
import { Component, OnInit, Input } from '#angular/core';
import { HolidayService } from '../holiday.service';
#Component({
selector: 'app-holiday',
templateUrl: './holiday.component.html',
styleUrls: ['./holiday.component.css']
})
export class HolidayComponent implements OnInit {
constructor(private _holiday: HolidayService) {
}
holidaysObj: any;
holidayArr: Array<{key: string, value: string}>;
ngOnInit() {
}
holidayParams(country,month){
this._holiday.getHolidays(country.value,month.value)
.subscribe(responseDa
ta => {
this.holidaysObj = responseData;
console.log(responseData);
});
this.convertObj(this.holidaysObj);
}
convertObj(obj : any){
for(const prop in obj){
if(obj.hasOwnProperty(prop)){
this.holidayArr.push(obj[prop]);
}
}
}
}
It works just fine when the response is called with filtering params, like 'month' and returns something like this:
{
"status": 200,
"holidays": [
{
"name": "Festivus",
"date": "2016-12-23",
"observed": "2016-12-23",
"public": true
},
{
"name": "Decemberween",
"date": "2016-12-25",
"observed": "2016-12-25",
"public": false
},
{
"name": "Winter Veil",
"date": "2016-12-25",
"observed": "2016-12-26",
"public": true
}
]
}
You can use a custom pipe to iterate your Objects, you could also extract the data from holidays from your response like:
.map(res => res.json().holidays)
but here I won't do it.
So let's create the custom pipe:
#Pipe({
name: 'keys'
})
export class KeysPipe implements PipeTransform {
transform(value: any, args?: any[]): any[] {
// check there is value to iterate
if(value) {
// create instance vars to store keys and final output
let keyArr: any[] = Object.keys(value),
dataArr = [];
// loop through the object,
// pushing values to the return array
keyArr.forEach((key: any) => {
dataArr.push(value[key]);
});
// return the resulting array
return dataArr;
}
}
}
and then you can use it in the template like:
<div *ngFor="let d of data?.holidays | keys">
<div *ngFor="let a of d">
{{a.name}}
{{a.date}}
<!-- rest of the properties -->
</div>
</div>
Here's a
Demo
UPDATE:
Alternatively, if you want to make your data to the same format as the other data you are receiving, you can manipulate the response. Like you mentioned, you need an if else statement first to check in which format the data is. In case the data is in the format like presented in question, you can do the following to reach the desired result:
.subscribe(data => {
// add statuscode
this.data = {status:data.status,holidays:[]}
let keyArr: any[] = Object.keys(data.holidays);
keyArr.forEach((key: any) => {
// push values of each holiday
this.data.holidays.push(data.holidays[key][0]);
});
})
Demo
I have the following json api document:
{
"data": [
{
"type": "haves",
"id": "2708f443-0857-4ae9-9935-9aa4b4e9f721",
"attributes": {
"quantity": 1
},
"relationships": {
"card": {
"data": {
"type": "cards",
"id": "3be08f31-3361-404c-9977-23535ed837f3"
}
}
}
}
],
"included": [
{
"type": "cards",
"id": "3be08f31-3361-404c-9977-23535ed837f3",
"attributes": {
"name": "Name"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "0fec70de-02e0-4646-bdcf-f86acea90d23"
}
}
}
},
{
"type": "sets",
"id": "0fec70de-02e0-4646-bdcf-f86acea90d23",
"attributes": {
"name": "Name"
}
}
]
}
With the following ember models:
// app/models/have.js
export default DS.Model.extend({
quantity: DS.attr('number'),
minPrice: DS.attr('number'),
account: DS.belongsTo('account'),
card: DS.belongsTo('card')
});
// app/models/set.js
export default DS.Model.extend({
name: DS.attr('string'),
cards: DS.hasMany('card')
});
// app/models/card.js
export default DS.Model.extend({
name: DS.attr('string'),
set: DS.belongsTo('set'),
haves: DS.hasMany('have')
});
And a custom inflector rule:
inflector.irregular('have', 'haves');
When I load the json document with this structure though, I can't seem to do something like have.card.set.name in my template when I iterate this jsonapi document. I'm guessing my jsonapi structure is incorrect. What am I missing? I don't get any errors in my chrome console or in the ember server running. When I load Ember Inspector, I see the set model under Data.