Map JSON in Angular 9 - json

I designed an app using Angular which is linked to a DB using a backEnd made with ASP.NET
My problem is that my JSON in the Front is a little different that the JSON in the backEnd.
And I need help on how to map the frontEnd JSON to send it to the backEnd.
psd: i created all the interfaces on the frontend, and I'm usign formControls and FormArrays to store the data in the front, the problem is that de JSON are a bit different.
I cannot change the JSON on the backEnd because is linked with the DB and it has PK and FK so that's the reasson because it's a bit different.
I was thinking about doing something like this.myform.value and map to the other interface, but i have no idea on how to do that because i have array of arrays...
Maybe a for loop?
Here is my frontEnd JSON:
{
"non-array fields....................." : "bla bla",
"arraySustancias": [
{
"sustanciaActiva": "hello",
"contenido": "2",
"suministro": ["hello2","hello3"],
"unidades": "3"
}
],
"arrayProcedimientos": [
{
"procedimiento": "",
"fechaInicioProcedimiento": "",
"fechaFinProcedimiento": "",
"notasProcedimiento": "",
"arraySubprocedimientos": [
{
"subprocedimiento": "",
"fechaInicioSubProcedimiento": "",
"fechaFinSubProcedimiento": "",
"notasSubProcedimiento": "",
"exp": ""
}
]
}
]
}
And here is my backEnd JSON:
{
"non-array fields.....................": "bla bla",
"registros_arraySustancias": [
{
"registros_arraySustancias_suministro": [
{
"registros_arraySustancias_id": "",
"id": "",
"value": [
"ABBOTT LABORATORIES",
"ADAMA Agan Ltd."
]
}
],
"registros_id": "",
"id": "",
"sustanciaActiva": "hola",
"contenido": 2,
"unidades": 3
}
],
"registros_arrayProcedimientos": [
{
"registros_id": "",
"id": "",
"procedimiento": "text",
"fechaInicioProcedimiento": "18/06/2020",
"fechaFinProcedimiento": "18/06/2020",
"notasProcedimiento": "notes",
"registros_arrayProcedimientos_arraySubprocedimientos": [
{
"registros_arrayProcedimientos_id": "",
"id": "",
"subprocedimiento": "text",
"fechaInicioSubProcedimiento": "19/06/2020",
"fechaFinSubProcedimiento": "19/06/2020",
"notasSubProcedimiento": "notes"
}
]
}
]
}
Thanks for your help :)

In that case I think you have to work a little bit with angular forms so that data from frontend should be from the same structure. FormGroups and FormArayys will help you alot.
Try looking at this article as well.
http://www.howilearnt.com/web-development/angular/make-a-json-object-with-angular-forms/

You simply create an object from your original object. There is no magic or automatic way to do that. Example:
interface OriginalData {
foo: string;
baz: {
test: number[]
};
}
interface MyData {
foobar: string;
bazTest: number[];
}
function getData(): Observable<OriginalData> {
return this.http.get<OriginalData>(url);
}
function convertData(original: OriginalData): MyData {
const res: MyData = {
foobar: original.foo,
bazTest: original.baz.test
};
return res;
}
// somewhere in your code
getData().subscribe(
v => sendData(convertData(v))
);
I'm using the Angular http client here, because you added the tag "angular". It will give you an object of the type you specified.

That was what I was looking for:
mapeado = {
pais: "",
registros_arraySustancias: [{
unidades: "",
contenido: 2,
sustanciaActiva: "",
registros_arraySustancias_suministro: [{value: [""]}]
}
]
}
Thanks a lot for your help

Related

How to get data of a JSON file (typescript)

Hi I got a bit stuck at trying to understand how to fetch data of a JSON file.
environment.ts:
export const environment = {
production: false,
urlListBooks: "/assets/list-books.json",
urlGetBooks: "/assets/edit-book.json?:id",
urlGetTags: "/assets/edit-book.json?:tags",
urlPostBooks: "/assets/edit-book.json",
urlListTags: "/assets/list-tags.json",
urlPostTags: "/assets/edit-tag.json"
};
edit-book.json:
"book":{
"id": 1,
"title": "The Shining",
"authorId": 1,
"tags": [{"name":"new"}, {"name":"test"}]
},
"authors":[
{
"id": 1,
"prename": "Stephen",
"surname": "King"
},
{
"id": 3,
"prename": "Algernon",
"surname": "Blackwood"
},
{
"id": 4,
"prename": "Edgar Allan",
"surname": "Poe"
},
{
"id": 5,
"prename": "Howard Phillips",
"surname": "Lovecraft"
}
],
"tags":[
{
"name": "new"
},
{
"name": "Horror"
},
{
"name": "Romance"
}
]
}
service:
getBookTags(n: String) Observable<Tag[]>{
return this.http.get<Tag[]>(environment.urlGetTags.)
}
what I want getBookTags(n: String) to do is returning the tags array of the book with title n defined in the edit-book.json (e.g. "tags": [{"name":"new"}, {"name":"Horror"}] ) so that I can later use the function to check which tags a book has and select them.
Your help would be very appreciated :)
Ok I think I've solved this for you, I'm going to walk through my process with you so you understand what the goal is. You can see my solution here: https://codesandbox.io/s/thirsty-minsky-g6959f?file=/assets/edit-book.json:0-752
First thing is that your JSON you provided doesn't really make much sense, it shows multiple authors and just one "book". I think instead you want multiple books. Secondly, it's gotta be wrapped in a curly brace as shown:
{
"books": [
{
"id": 1,
"title": "The Shining",
"authorId": 1,
"tags": [{ "name": "new" }, { "name": "test" }]
},
{
"id": 2,
"title": "The Wendigo",
"authorId": 2,
"tags": [{ "name": "Horror" }]
}
],
"authors": [
{
"id": 1,
"prename": "Stephen",
"surname": "King"
},
{
"id": 3,
"prename": "Algernon",
"surname": "Blackwood"
},
{
"id": 4,
"prename": "Edgar Allan",
"surname": "Poe"
},
{
"id": 5,
"prename": "Howard Phillips",
"surname": "Lovecraft"
}
],
"tags": [
{
"name": "new"
},
{
"name": "Horror"
},
{
"name": "Romance"
}
]
}
Now, in your Typescript code we want to have typings for the json you're going to fetch. This will make your code more readable, it will give you intellisense, and help you catch some errors before you try to run your code. So we are going to go ahead and type the properties of the JSON as follows:
type Tag = {
name: string;
};
type Book = {
id: number;
title: string;
authorId: number;
tags: Tag[];
};
type Author = {
id: number;
prename: string;
surname: string;
};
type BookData = {
books: Book[];
authors: Author[];
tags: Tag[];
};
Basically what I said is we have bookdata which is made up of books, authors, and tags. Books have properties given under type Book, same thing with Author and Tag.
Now for the actual running code, we are going to use the fetch api to get the json data at the url.
async function getBookTags(n: string): Promise<Book[]> {
return fetch(url)
.then<BookData>((res) => res.json())
.then((data) => data.books)
.then((books) => books.filter((b) => doesBookHaveTag(b, n)));
}
First thing we do is fetch the data from the api, this returns a promise which when resolved (this is what .then does) we take the response and parse it for a json. Then when that promise resolves we get the books in the data. Then when that promise resolves we filter in books that have the matching tag.
doesBookHaveTag is just a little helper function I defined:
function doesBookHaveTag(book: Book, n: string): boolean {
// just return if book has at least one tag matching n
return book.tags.some((t) => t.name.toLowerCase() === n.toLowerCase());
}
If you don't understand promises you should watch some videos on it, but basically the browser sends out an http request and then when it resolves it queues a task to execute the function [see endnote] in .then when it has time. So when we want to call your async function and say log all books with the tag "horror" we do it as shown:
getBookTags("horror").then(console.log); // returns the one book.
I hope this makes sense and you can sort of see how to fetch the data, how to handle the promise it returns, and how to type your response. The only thing I'm not sure on is how Angular changes this for you (I'm a react guy), but this is really just non-library specific Javascript/Typescript.
[endnote] when I say function in .then, what I mean is that .then(data => data.books) is passing a function into the .then function. data => data.books is actually a function the same as:
function(data: BookData): Book[] {
return data.books
}

Hapi response doesn't show tree-like (nested) json

Ok, so I have an object that has the following structure:
interface FolderWithContent {
uuid: string
name: string;
folders: Array<FolderWithContent>;
files: Array<Files>;
}
Where Files is an extension of Sequelize.Model.
And I'm trying to return it with hapi (return h.response(tree).code(200);) (tree is my object, of course)
The thing is, my object has several levels and the response is only showing the root and 1st level. So if I have
{
"name": "folder1.1",
"uuid": "1",
"folders": [
{
"name": "folder2",
"uuid": "3986b8ca-314c-4ba8-b47c-9baa29ca7adc"
},
{
"name": "folder2.6",
"uuid": "7ff93401-1281-419c-9541-fb859c4e79e1",
"folders": [
{
"name": "folder3.1",
"uuid": "8d76aa76-fa42-40c6-9c46-9fa26c6b555c"
}
],
"files": [
{
"name": "file5",
"uuid": "9a8c9aa2-23bd-45e3-bb43-ddf0e085b066"
}
]
}
],
"files": [
{
"name": "file2.2.2",
"uuid": "88519cec-b19a-4e12-9138-6273ac66ba76"
},
{
"name": "file1",
"uuid": "9eb5235d-9d04-494d-845c-4a9780bc9687"
}
]
}
I will not get folders and files inside of folder2.6.
I have tried to return tree.folders[2], but it still only shows the folder name and uuid. However, if i return tree.folders[2].folders, only then it shows me the folders and files inside folder2.6.
I have tried calling Json.stringfy(tree) but it also has the exact same problem.
I still don't know WHY I had the problem, but I'm posting the way I found to fix it.
Turns out the issue was with sequelize. All the objects were models from sequelize. Converting the objects to simple JSONs did it for me.
tree.folders = content.folders?.map((folder) => {
return {
name: folder.name,
uuid: folder.uuid,
updated_at: folder.updated_at,
synced: folder.synced,
folders: [],
files: []
};
});
tree.files = content.files?.map((file) => {
return {
name: file.name,
uuid: file.uuid,
updated_at: file.updated_at,
synced: file.synced
};
});

Access nested JSON in React table

I want to display nested JSON data in a react-table.
I tried it like this:
render() {
const columns = [{
//Not Displaying
Header: 'Owner ID',
id: 'ownerid',
accessor: '_links.customer.href.ownerid', // <- i think this is wrong
Cell: this.renderEditable
},
{
//Displaying
Header: 'Price',
accessor: 'price',
Cell: this.renderEditable
}, {
The data i am getting back and have bound to the table is structured as follows:
[
{
"id": 1,
"date": "20.07.2019",
"price": 3.2,
"customer": {
"ownerid": 1,
"firstname": "John",
"lastname": "Johnson"
}
}
]
Here i am using the columns array:
import ReactTable from "react-table";
<ReactTable data={this.state.offers} columns={columns}
filterable={true} pageSize={10}/>
Binding the data:
fetchOffers = () => {
const token = sessionStorage.getItem("jwt");
fetch(SERVER_URL + 'api/offers',
{
headers : {'Authorization':token}
})
.then((response) => response.json())
.then((responsteData) => {
this.setState({
offers: responsteData._embedded.offers,
});
console.log(this.state);
})
.catch(err=> console.error(err));
}
The data i am using after binding:
Check the Accessors documentation. It has several examples for complex data structure.
I don't see _links or href in your sample data. So I think that you need just:
accessor: 'customer.ownerid'
The data structure from the console screenshot doesn't match your sample data. And it doesn't seem to contain ownerid. Try accessor: '_links.customer.href' to check whether it outputs anything to the table.
I figured it out.
I called the endpoint "localhost:8080/api/offers" and saved the following response:
"offers": [
{
"date": "20.07.2019",
"price": 3.2,
"_links": {
"self": {
"href": "http://localhost:8080/api/offers/1"
},
"offer": {
"href": "http://localhost:8080/api/offers/1"
},
"customer": {
"href": "http://localhost:8080/api/offers/1/customer"
}
}
}
]
there is no customer object
But when i call "localhost:8080/offers" i get:
[
{
"id": 1,
"date": "20.07.2019",
"price": 3.2,
"customer": {
"ownerid": 1,
"firstname": "John",
"lastname": "Johnson"
}
}
]
i changed the URI in my project and now the number is displaying.
I still don't know why i get data from "../api/offers" but i will research.
I had to access a nested object and display it with some styling, and this ended up working for me:
(Note: I was using typescript, so some of the typing might not be necessary)
{
Header: 'Thing To Display',
accessor: 'nested.thing.to.display',
Cell: ({ row }: { row: Row }) => (
<p>{row.values['nested.thing.to.display']}</p>
),
}

Angular 2: How to modify json feed before giving it to template

From json I get this:
{
"name": "Leonardo",
"weapon": "sword"
},
{
"name": "Donatello",
"weapon": "stick"
},
{
"name": "Michelangelo",
"weapon": "nunchucks"
},
{
"name": "Raphael",
"weapon": "sai"
}
But for template I want to insert one extra field dynamically:
{
"name": "Leonardo",
"weapon": "sword"
"is_leader": "true"
},
{
"name": "Donatello",
"weapon": "stick"
"is_leader": "false"
},
{
"name": "Michelangelo",
"weapon": "nunchucks"
"is_leader": "false"
},
{
"name": "Raphael",
"weapon": "sai"
"is_leader": "false"
}
But I can't even get component to return the observable (says it's undefined, but renders ok in template). So far I have this in my component.
constructor(private dataService: DataService) {
this.dataSubscription = this.dataService.getTestData().subscribe(res => this.allData = res);
}
You should modify the data from .map()
Here is the logic how you can achieve that will current given code :
.subscribe(res => {
this.allData = res.map(e => {
e['is_leader'] = true; // as per your rule;
return e;
});
});
With HttpClient which came with Angular 4.3+, you could use interceptors (HttpIntercept) to intercept, filter and/or modify you incoming JSON feed. A bit of googling shows how to setup interceptors and use them like here for example.

Access Array inside an object (json)

I have this json file and I want to access the array that is inside this object:
best-sellers": [
{
"title": "Chuteira Nike HyperVenomX Proximo II Society",
"price": 499.90,
"installments": {
"number": 10,
"value": 49.90
},
"high-top": true,
"category": "society",
"image": ""
},
{
"title": "Chuteira Nike HyperVenom Phantom III Cano Alto Campo",
"price": 899.90,
"installments": {
"number": 10,
"value": 89.90
},
"high-top": true,
"category": "campo",
"image": ""
}
}
]
This is the code on my component:
ngOnInit(): void {
this.service
.lista()
.subscribe(chuteiras =>{
this.chuteiras = chuteiras;
})
}
and my template looks like this:
<div *ngFor="let chuteira of chuteiras.best-sellers">
But angular is not reconigzing it the `best-sellers", here's the error that I'm getting:
Cannot read property 'best' of undefined
Just use bracket notation,
<div *ngFor="let chuteira of chuteiras["best-sellers"]">
well,that's one way of doing it but angular 6 came with a simple solution. when i was faced with this problem i myself resolved to this solution but it didn't work for me so after searching and making my own touches i ended up with this solution.
1.create the function to receive the JSON data in my case i used a web API
getTrending() {
return this.http.get(https://api.themoviedb.org/3/trending/all/day?api_key=${this.api_key});
}
2.call the function in my case i used a service, so after import it to my component i simply added this
showPopular(): void {
this.api.getTrending().subscribe((data: Array<object>) => {
this.list = data['results'];
console.log(this.list);
});
}
as you can see the data variable only accessed the information i required.