0

This question is maybe not 100% original but the questions/answers I've found so far seem to neglect a certain elephant in the room.

I have a situation which I'll simplify for example's sake. Let's say I have the following JSON response:

[
  {
    "place": {
      "name": "The Cottage",
      "rating": 4
    }
  },
  {
    "place": {
      "name": "El Burrito Loco",
      "rating": 5
    }
  }
]

Then let's say I want to have a Typescript class called Place. If I instantiate each element as a Place, I have this stupid situation:

<!-- this is an Angular template -->

<ul>
  <li *ngFor="let place of places">{{ place.place.name }}</li>
</ul>

What I would prefer, of course, is {{ place.name }} rather than {{ place.place.name }}.

So my question is: how can I transform a JSON response to match my data model?

I've already seen questions/answers like this one.

What confuses me is that a) I imagine that this transformation desire is an incredibly common one, and b) all the answers I've found so far seem to involve a ton of hacky boilerplate (no offense).

So what's the deal, does everybody just copy and paste all this boilerplate into their apps to meet what must be a very common need, and the TypeScript (or Angular) developers just didn't come up with a way to meet this need with the language or framework? That doesn't seem likely. It's very confusing.

Any insight is very much appreciated.

1

3 Answers 3

1

I can think of simple map function over API call observable, which will create desired object structure in Place object model format.

this.dataService.getPlaces()
  .map(data => data.json())
  .map(items => items.map(
    item => <Place>({item.place.name, item.place})
  )
);
Sign up to request clarification or add additional context in comments.

8 Comments

Ah, I can see how this would work, although there are some other properties (which I didn't include in my example) that I need to preserve.
@JasonSwett How often this is going to happen.. for few objects writing your own custom map would make sense.
This particular transformation would presumably only need to happen in one or two places. Transformations in general might need to happen on any number of resources.
@JasonSwett for one or two places having custom map would make sense for me. Going forward you should avoid such object format which are receiving from API, this implication will ensure that this kind of custom mapper will introduce again in application.
I ended up doing something different from what you suggested but I upvoted your answer because it helped get me on the right track.
|
0

JSON.parse actually supports an optional reviver argument that allows you to control the creation of any given property during the deserialization process. You should be able to use that to create an instance of your class.

Comments

0

Here's what I ended up doing. Thanks to Pankaj Parkar for providing some clues that led me here.

  getList(): Observable<Place[]> {
    return this.http.get(this.placesUrl)
               .map(response => response.json().data)
               .map(data => data.map((item) => {
                 return <Place>({
                   name: item.place.name,
                   place: item.place
                 });
               }));
  }

1 Comment

Downvoter, please explain your downvote. This is the exact code that solved my issue.

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.