Search code examples
jsonangularangular-httpclient

Angular HttpClient returns string data instead of parsed JSON


I've been in the process of migrating a code base from Angular 4.x to 5.x, and I'm running into a strange issue. I have a service function, that is intended to return a list of objects to the front end, which I then massage into a specific data format. I know I'll need to keep the mapping, but I'm a little miffed that it's returning just plain string data.

The original function is this: (using Http from @angular/http just renamed to HttpClient)

    public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
        let link = AppSettings.API_COMMON_VENDORS;
        let params: URLSearchParams = new URLSearchParams();
        params.set('showAll', showAll.toString());
        params.set('screenArea', screenArea.toString());

        let requestOptions = new RequestOptions();
        requestOptions.search = params;

        return this.httpClient.get(link, requestOptions).map(response => {
            let result = JSON.parse(response.json());
            let list = new Array<SelectModel>();
            let vendors: Array<any> = result;

            vendors.forEach(vendor => {
                list.push(this.CreateSelectModel(vendor));
            });

            return list;
        });
    }

and after ripping out ALL of the Http code, here's the function again using HttpClient from @angular/common/http

    public GetVendors(showAll = true, screenArea: number = 0): Observable<Array<SelectModel>> {
        let link = AppSettings.API_COMMON_VENDORS;
        let params: HttpParams = new HttpParams()
            .set('showAll', showAll.toString())
            .set('screenArea', screenArea.toString());

        return this.httpClient.get<Array<any>>(link, {params}).map(response => {
            let list = new Array<SelectModel>();

            response.forEach(vendor => {
                list.push(this.CreateSelectModel(vendor));
            });

            return list;
        });
    }

The issue with this is it kind of defeats the purpose of the new client parsing json for me. The response object is a string representing the JSON of the data I requested, but it's still in a string form, and not the type defined in the get<>() call.

What am I doing wrong here? shouldn't it be parsed already?

Sample Response Data A'la Network Tools in Chrome Dev Tools: enter image description here

Sample Response Body:

enter image description here

Dev Tools Screenshot with Value of response enter image description here

The backend (C#) responds with this:

      [HttpGet]
        public JsonResult Vendors(bool showAll = false, int screenArea = 0)
        {
            var vendors = _commonBL.GetVendorsSlimForUser(UserModel, UserModel.CustomerId, showAll, screenArea);

            return GetJson(vendors);
        }

this is how it worked before the Http => HttpClient migration, and it worked with ONE JSON.parse() The data in the return line is simply a standard List<T>


Solution

  • This is what the raw response for your data should look like:

    [{"Id":1234,"Name":"Chris Rutherford"}]
    

    But this is what it actually looks like:

    "[{\"Id\":1234,\"Name\":\"Chris Rutherford\"}]"
    

    So somewhere in your server code, you have applied JSON encoding twice. Once you correct that, HttpClient will do the right thing.