错误状态:无法设置内容类型为“application/json”的请求的正文字段

Posted

技术标签:

【中文标题】错误状态:无法设置内容类型为“application/json”的请求的正文字段【英文标题】:Bad state: Cannot set the body fields of a Request with content-type "application/json" 【发布时间】:2019-07-17 21:13:25 【问题描述】:
Map<String,String> headers = 'Content-Type':'application/json','authorization':'Basic c3R1ZHlkb3RlOnN0dWR5ZG90ZTEyMw==';

var response = await post(Urls.getToken,
        headers: headers,
        body: "grant_type":"password","username":"******","password":"*****","scope":"offline_access",
      );

当我执行此操作时,我无法接收数据并且抛出的错误是

【问题讨论】:

试试 - body: json.encode("grant_type":"password","username":"******","password":"*****","scope":"offline_access"), 请注意,您还发布了您的username/password,即使他们可能是测试用户,这不是一个好习惯... 【参考方案1】:

你需要将body包裹在jsonEncode中。

import 'package:http/http.dart' as http;
import 'dart:convert';

Map<String,String> headers = 'Content-Type':'application/json','authorization':'Basic c3R1ZHlkb3RlOnN0dWR5ZG90ZTEyMw==';
final msg = jsonEncode("grant_type":"password","username":"******","password":"*****","scope":"offline_access");

var response = await post(Urls.getToken,
               headers: headers,
               body: msg,
            );

【讨论】:

谢谢!起初我没有看到你的答案和问题之间的区别,但现在我看到关键是将地图文字包装在 jsonEncode【参考方案2】:

jsonEncode包裹你的身体object

import 'package:http/http.dart' as http;
import 'dart:convert';

var headers = 
    'Content-Type':'application/json',
    'authorization':'Basic c3R1ZHlkb3RlOnN0dWR5ZG90ZTEyMw=='
;

final body = 
    'username':'foo',
    'password':'pass123'


var response = await post(
    Urls.getToken,
    headers: headers,
    body: jsonEncode(body), // use jsonEncode()
);

为什么是jsonEncode

body:可以是 html、JSON 或 XML 等。这意味着我们需要以特定格式发送/接收数据。您可以在content-type 标头中设置它,其默认值为text/plain

当您将content-type 标头设置为JSON 时,您必须将“有效”JSON 作为正文传递。但是您将Map&lt;String, String&gt; 作为正文传递,这显然会引发错误。

因此,要解决此问题,您需要将您的 Map&lt;String, String&gt; 数据更改(或 encode)为 JSON 数据。

最好的方法是使用jsonEncode 函数。

【讨论】:

【参考方案3】:

http 库有类似问题...更改为 dio 2.1.0 并且标头问题消失了。

jsonEncode(body) 没有做到这一点,因为文档说:

发送带有给定标头和正文的 HTTP POST 请求到给定的 URL,可以是 [Uri] 或 [String]。

[body] 设置请求的正文。它可以是 [String]、[List] 或 [Map]。如果它是一个字符串,它是使用编码的 [编码] 并用作请求的正文。的内容类型 请求将默认为“text/plain”。

如果 [body] 是一个 List,它被用作 请求。

如果 [body] 是 Map,则使用 [encoding] 将其编码为表单字段。这 请求的内容类型将设置为 "application/x-www-form-urlencoded";这不能被覆盖。 [编码] 默认为 [utf8]。

要对请求进行更细粒度的控制,请改用 [send]。

Future<Response> post(url, Map<String, String> headers, body, Encoding encoding);

【讨论】:

【参考方案4】:
Map<String,String> header = 'Content-Type':'application/json-patch+json','accept':'application/json';
    final msg = jsonEncode("username":"$emailorPhoneN","password":"$passwrod");

    try 
      var response = await http.post(UrlConstants.loginUrl, headers: header, body: msg,
      ).timeout(Duration(seconds: httpDuration));
      var convert = json.decode(response.body);
      print('**********Data from server $convert');

      if (convert == null) 
        return null;
       else 
        String token = convert['token'];

        if (token != null) 
          SignUpModel signUpModel = SignUpModel.fromJson(convert);
          return signUpModel;
         else 
          //*** GET Error message from the API provider.....
          SignUpModel signUpModel = SignUpModel.fromJson(convert);
          return signUpModel;
        
      

【讨论】:

【参考方案5】:

异常是由于设置不正确的bodyFields引起的。 见:bodyFields

bodyFields 用于 form-encoded 数据,而不是 JSON。 有关如何 POST JSON 的示例,请参阅:Write HTTP servers

因此,您尝试将 Map 作为主体传递。在这种情况下,它会假设您实际上正在执行application/x-www-form-urlencoded。您需要做的是将Map 编码为字符串,然后执行您正在执行的操作。

例子

  Future<http.Response> patchAPICall(
      String url, Map param, String token) async 
    var responseJson;
    try 
      final response = await http.patch(Uri.parse(url),
          body: jsonEncode(param),
          headers: 
            "Authorization": token,
            "Content-Type": "application/json"
          ).timeout(const Duration(seconds: 60),
          onTimeout: () => throw TimeoutException(
              'The connection has timed out, Please try again!'));
      responseJson = response;
     on SocketException 
      throw FetchDataException("You are not connected to internet");
     on TimeoutException 
      print('Time out');
      throw TimeoutException("The connection has timed out, Please try again");
    
    return responseJson;
  

【讨论】:

【参考方案6】:

对我来说,jsonencode(body) 不起作用。 这对我有用:

body = json.encode(body);
http.post(Uri.parse(uri), headers: header, body: body);

【讨论】:

以上是关于错误状态:无法设置内容类型为“application/json”的请求的正文字段的主要内容,如果未能解决你的问题,请参考以下文章

打字稿错误类型无法分配给状态 - usestate

JPQL:错误编译 - 状态字段“e.e2.e3”无法解析为有效类型

无法将状态栏设置为浅色内容(iOS7)

内容类型应用程序/soap+xml; charset=utf-8 不受服务支持

与 ES7 反应:未捕获的类型错误:无法读取未定义的属性“状态”[重复]

未捕获的类型错误:无法设置未定义的属性(设置“isSubcon”)