【问题标题】:Angular HttpClient returns string data instead of parsed JSONAngular HttpClient 返回字符串数据而不是解析的 JSON
【发布时间】:2021-03-15 07:09:14
【问题描述】:

我一直在将代码库从 Angular 4.x 迁移到 5.x,但遇到了一个奇怪的问题。我有一个服务功能,旨在将对象列表返回到前端,然后我将其按摩成特定的数据格式。我知道我需要保留映射,但我有点生气它只返回纯字符串数据。

原来的功能是这样的:(使用来自@angular/http的Http刚刚改名为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;
        });
    }

在删除所有 Http 代码后,再次使用来自 @angular/common/httpHttpClient 的函数

    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;
        });
    }

问题在于它有点违背了新​​客户端为我解析 json 的目的。 response 对象是一个字符串,表示我请求的数据的 JSON,但它仍然是字符串形式,而不是 get&lt;&gt;() 调用中定义的类型。

我在这里做错了什么?不应该已经解析了吗?

Chrome 开发工具中的 A'la Network Tools 响应数据示例:

示例响应正文:

值为response 的开发工具屏幕截图

后端 (C#) 响应如下:

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

            return GetJson(vendors);
        }

这是在 Http => HttpClient 迁移之前的工作方式,它与 ONE JSON.parse() 一起工作,返回行中的数据只是一个标准的List&lt;T&gt;

【问题讨论】:

  • 默认情况下应该。检查浏览器的调试工具并导航到网络调用选项卡。查找对该端点进行的网络调用。 http 标头是否包含正确的 content-type 标头和值 json?那么响应呢,它是一个数组还是一个包含数组的对象?
  • 是的,它以 application/json 的形式返回,但仍然是一个字符串。
  • 您没有回答我评论中的第二个问题。请在您的问题中包含逐字响应消息正文以及响应 http 标头。网络信息的屏幕截图也是可以接受的。
  • 顺便说一句,GetJson 是什么?这不是System.Web.Mvc.Controller 的方法,我也找不到System.Web.Mvc.Controller 的扩展方法。也许您可以轻松修复服务器端代码,但您必须在问题中包含如何调用它。
  • 但是GetJson 是什么?这不是 mvc 库中包含的调用,因此它可能是您代码中的自定义实现。请在您的问题中包含该方法的实现。

标签: json angular angular-httpclient


【解决方案1】:

这是您数据的原始响应应该的样子:

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

但这就是它实际上的样子:

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

因此,在您的服务器代码的某个地方,您已经应用了两次 JSON 编码。一旦你更正了,HttpClient 就会做正确的事。

【讨论】:

    【解决方案2】:

    我会引用this thread 的回答。希望它能对事情的工作原理有所启发,仔细阅读它,它启发了我,很难找到它。

    TypeScript 仅在编译时验证对象接口。代码在运行时获取的任何对象都无法验证 打字稿。

    如果是这种情况,那么像 HttpClient.Get 这样的东西不应该 返回 T 类型的 Observable。它应该返回 Object 类型的 Observable,因为 这就是实际返回的内容。试图声明它返回 T 当它返回 Object 时会产生误导。

    在文档中,客户的退货部分是这样说的:

    @return 正文的Observable 为 输入T

    实际上,文档应该说:

    @return 一个 Observable 的正文 可能是T。你没有得到 T 回来。如果你把 T 拿回来,它会 实际上是 T,但不是。

    【讨论】:

    • 我能理解到最后部分。
    • @ChrisRutherford 编辑为易于理解,但请阅读链接文章,它将对您有所帮助
    猜你喜欢
    • 2018-09-20
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多