J'obtiens donc la structure JSON suivante de mon asp.net core
api:
{
"contentType": null,
"serializerSettings": null,
"statusCode": null,
"value": {
"productName": "Test",
"shortDescription": "Test 123",
"imageUri": "https://bla.com/bla",
"productCode": null,
"continuationToken": null
}
}
J'ai la fonction dactylographiée suivante qui appelle l'API pour obtenir la réponse ci-dessus:
public externalProduct: ProductVM;
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map((data: ProductVM) => {
this.externalProduct = data; //not working...
console.log("DATA: " + data);
console.log("DATA: " + data['value']);
return data;
});
}
ProductVM:
export interface ProductVM {
productName: string;
shortDescription: string;
imageUri: string;
productCode: string;
continuationToken: string;
}
Mon problème est que je ne peux pas le désérialiser en ProductVM
. Les journaux de la console produisent simplement [object Object]
Comment puis-je mapper le contenu de value
dans ma réponse json à un objet ProductVM
?
Est-il faux de dire que data
est un ProductVM
dans la fonction de carte? J'ai essayé beaucoup de combinaisons différentes mais je n'arrive pas à le faire fonctionner!
Je ne sais pas si je peux dire automatiquement à angular
de mapper le tableau de valeurs dans la réponse json
à un objet ProductVM
ou si je dois fournir un constructeur au ProductVM
class (c'est une interface en ce moment), et extraire manuellement les valeurs spécifiques dans le json
?
5 réponses
L'objet data
dans la méthode map chaînée à http est considéré comme un objet typé Object
. Ce type n'a pas le membre value
auquel vous devez accéder et par conséquent, le vérificateur de type n'est pas satisfait.
Les objets qui sont typés (qui ne sont pas any
) ne peuvent être affectés qu'à des objets non typés ou du même type exact. Ici, vos données sont de type Object
et ne peuvent pas être affectées à un autre objet de type ProductVM
.
Une solution pour contourner la vérification de type consiste à convertir votre objet de données en un objet any
non typé. Cela permettra d'accéder à n'importe quelle méthode ou membre, tout comme l'ancien Javascript.
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map((data: any) => this.externalProduct = data.value);
}
Une autre solution consiste à modifier votre API afin que les données puissent diffuser leur contenu avec data.json()
. De cette façon, vous n'aurez pas à contourner la vérification de type puisque la méthode json () renvoie une valeur non typée.
Attention cependant car votre objet any
n'aura pas de méthodes du ProductVM
si jamais vous les ajoutez dans le futur. Vous devrez créer manuellement une instance avec new ProductVM()
et Object.assign
dessus pour accéder aux méthodes.
J'ai utilisé cette approche dans un client qui utilise la méthode
HttpClient.get<GENERIC>(...).
Maintenant ça marche. Quoi qu'il en soit, je ne comprends pas pourquoi je ne reçois pas un type de T en retour du client http, si je n'utilise pas la solution fournie dans la réponse ci-dessus.
Voici le client:
// get
get<T>(url: string, params?: [{key: string, value: string}]): Observable<T> {
var requestParams = new HttpParams()
if (params != undefined) {
for (var kvp of params) {
params.push(kvp);
}
}
return this.httpClient.get<T>(url, {
observe: 'body',
headers: this.authHeaders,
params: requestParams
}).pipe(
map(
res => <T>res
)
);
}
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get("api/product?productCode=" + code)
.map(data => {
this.externalProduct = <ProductVM>data;
console.log("DATA: " + this.externalProduct);
return data;
});
}
Alors, nous convertissons d'abord la réponse en JSON. Je le stocke dans response
juste pour le rendre plus propre. Ensuite, nous devons naviguer vers value
, car dans vos données value
se trouve l'objet qui correspond à ProductVM
.
Je le ferais cependant comme ceci:
Service
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get(`api/product?productCode=${code}`)
.map(data => <ProductVM>data)
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
Composant
this.subscription = this.myService.getProductExternal(code).subscribe(
product => this.externalProduct = product,
error => console.warn(error)
);
Avez-vous essayé de remplacer
this.externalProduct = data;
Avec
this.externalProduct = data.json();
J'espère que cela aide
À partir de la documentation angulaire: réponse http Typechecking
Vous devez définir le type de données renvoyées lors de l'utilisation de new httpClient (depuis angular 4.3) => this.http.get < ProductVM > (...
public externalProduct: ProductVM;
getProductExternal(code: string): Observable<ProductVM> {
return this.http.get<ProductVM>("api/product?productCode=" + code)
.map((data: ProductVM) => {
this.externalProduct = data; // should be allowed by typescript now
return data;
});
}
Ainsi dactylographié devrait vous laisser en paix
Questions connexes
De nouvelles questions
json
JSON (JavaScript Object Notation) est un format d'échange de données sérialisable destiné à être lisible par machine et par l'homme. N'utilisez pas cette balise pour les objets JavaScript natifs ou les littéraux d'objet JavaScript. Avant de poser une question, validez votre JSON à l'aide d'un validateur JSON tel que JSONLint (https://jsonlint.com).