简体   繁体   中英

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 (eg "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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM