2

Suppose I had an api that returns the following JSON structure:

{
  "Response": {
    "status": {
      "code": "SUCCESS",
      "message": "owner found",
      "count": "1"
    },
    "owners": [
      {
        "ownerId": "12345",
        "name": "Example Person",
        "cars": [
          {
            "make": "Toyota"
            "year": "2004"
            "model": "Camry"
          } 
        ]
      }
    ] 
  }
}

I want to map this json structure into these typescript models:

export class ApiResponse{
  constructor(
    public status: Status,
    public owners: Owner[]
  ) {}
}
export class Status {
  constructor(
    public code: string,
    public message: string,
    public count: number
  ) {}
}
export class Owner{
  constructor(
  public ownerId: number,
  public name: string,
  public cars: Car[]
  ) {}
}
export class Car{
  constructor(
    public make: string;
    public year: string;
    public model: string;
  )
}

From my understanding of angular 7, you can use pipe and map from rxjs to achieve this:

this.http.get(url).pipe(
      map((data: any[]) => data.map((item: any) => new ApiResponse(
      new Status(
        item.status.code,
        item.status.message,
        item.status.count),
...

Using this I am able to map a JSON object, but I am unsure how to approach mapping arrays and nested arrays.

How should I approach mapping a JSON with nested arrays?

1
  • If your model definitions are really nothing but property lists, they are functionally equivalent to interfaces. As such, there's no need to instantiate new objects, because nothing is gained -- TS enforces type checking for interfaces as well as classes. Just return the Observable to the component for rendering. Commented Apr 17, 2019 at 20:05

1 Answer 1

2

If your classes will not implement any new functionality you should use interfaces just to enforce strong types, otherwise is just boilerplate. As you started you can derive your 4 interfaces like so and benefit from the Typescript safety check:

export interface ApiResponse{
    status: Status,
    owners: Owner[]
}
export interface Status {
    code: string,
    message: string,
    count: number
}
export interface Owner{
    ownerId: number,
    name: string,
    cars: Car[]
}
export interface Car{
    make: string;
    year: string;
    model: string;
}

Your method that calls that API can be written like this:

getStatusAndOwners(url): Observable<ApiResponse> {
    return this.http.get(url);
}

When you will consume the data (in the subscribe block most probably) you will benefit from "IntelliSense" and strong typing.

Good luck!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the response, this works as needed. Something to note is that I needed to cast the get function to fit the return value: this.http.get<ApiResponse>(url);
True, because we expect an Observable<ApiResponse>. Well done!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.