Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Ao trabalhar com Angular e o HttpClient para consumir APIs REST, um dos desafios mais comuns é lidar com a serialização e desserialização de respostas JSON, especialmente quando o formato retornado pelo backend difere do esperado pelos métodos padrão.
Por padrão, o HttpClient do Angular já realiza a desserialização automática do conteúdo retornado, eliminando a necessidade de usar o método json() como nas versões anteriores do Angular. Isso significa que, ao fazer uma requisição GET, o resultado já é um objeto JavaScript, não mais uma Response que precisa de json().
No entanto, muitos desenvolvedores iniciantes ou que migram de exemplos antigos podem tentar usar o método json() na resposta, levando a erros como "Property 'json' does not exist on type 'Object'". Além disso, quando o formato do JSON do backend não corresponde ao esperado, é comum receber erros de propriedades inexistentes, como no caso de tentar acessar 'results' ou 'data' em objetos que não possuem essas chaves.
A primeira coisa é entender que o HttpClient aceita um parâmetro genérico que informa o tipo esperado da resposta. Assim, você pode definir interfaces que representam a estrutura do JSON retornado pelo seu backend. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois.
Por exemplo, se sua API responde com um objeto do tipo:
{
"results": [
{...}, {...}
]
}
Você deve criar uma interface para esse formato:
export interface ApiResponse {
results: Order[]. }
E, na sua requisição, usar essa interface como tipo genérico:
return this.http.get<ApiResponse>(url).pipe(
map(response => response.results),
catchError(error => throwError(error.message || 'Erro na requisição'))
). A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte.
Assim, você evita o uso do json() e consegue acessar as propriedades de forma segura e compatível com o Angular moderno. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte.
import { HttpClient, HttpParams } from '@angular/common/http'. import { Injectable } from '@angular/core'. import { Observable, throwError } from 'rxjs'. import { catchError, map } from 'rxjs/operators'. export interface Order {
// propriedades do pedido
} O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
export interface ApiResponse {
results: Order[]. }
@Injectable({ providedIn: 'root' })
export class OrderService {
constructor(private http: HttpClient) {} Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
fetchOrders(startIndex: number, limit: number): Observable<Order[]> {
const params = new HttpParams()
.set('startIndex', startIndex.toString())
.set('limit', limit.toString()). return this.http.get<ApiResponse>(this.baseUrl, { params })
.pipe(
map(response => response.results),
catchError(error => throwError('Erro ao buscar pedidos'))
). }
} Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar.
Adaptar a sua requisição para esse padrão garante maior compatibilidade com o Angular atual, além de facilitar a manutenção ao lidar com mudanças no backend. Assim, você evita erros de propriedade inexistente e mantém o código limpo e previsível. A decisão fica mais saudável quando o time consegue medir o impacto depois. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar.
No meu time, a gente também criou um interceptor pra validar o formato do JSON antes de passar pra camada de negócio. Facilita bastante na hora de migrar versões.
Muito bom esse método, ajuda a evitar aquele problema de json() que não existe mais. No meu time, a maior dor era justamente na hora de gerar as interfaces corretas.
Exato, e o mais importante é sempre validar o formato de resposta, pra não depender de um campo específico que pode mudar. Melhor usar interfaces estritas.
Pois é, já passei por isso, tentar usar json() na resposta do Angular dá um trabalho depois. Acho que a chave é usar o tipo genérico e mapear direto na resposta.