【问题标题】:HTTP POST with Json on Body - Flutter/Dart主体上带有 Json 的 HTTP POST - Flutter/Dart
【发布时间】:2018-10-21 00:58:44
【问题描述】:

这是我向 API 发出请求的代码:

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

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  var body = jsonEncode({ 'data': { 'apikey': '12345678901234567890' } });

  print("Body: " + body);

  http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  ).then((http.Response response) {
    print("Response status: ${response.statusCode}");
    print("Response body: ${response.contentLength}");
    print(response.headers);
    print(response.request);

  });
  }

我对请求的响应有疑问,它假设有一个带有 json 的正文,但是出了点问题,我认为是我在正文请求中发送的 json,因为它是一个嵌套的 json 对象, 键的值是一个 json 对象。我很想知道如何正确解析 json 并插入到请求的正文中。

这是标题响应:

 {set-cookie: JSESSIONID=DA65FBCBA2796D173F8C8D78AD87F9AD;path=/testes2/;HttpOnly, last-modified: Thu, 10 May 2018 17:15:13 GMT, cache-control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0, date: Thu, 10 May 2018 17:15:13 GMT, content-length: 0, pragma: no-cache, content-type: text/html, server: Apache-Coyote/1.1, expires: Tue, 03 Jul 2001 06:00:00 GMT}

这是应该的:

Server: Apache-Coyote/1.1
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Last-Modified: Thu, 10 May 2018 17:17:07 GMT
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Set-Cookie: JSESSIONID=84813CC68E0E8EA6021CB0B4C2F245BC;path=/testes2/;HttpOnly
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked

正文响应为空,我认为这是因为我在请求中发送的正文,任何人都可以帮助我处理嵌套的 json 对象值吗??

邮递员的屏幕截图:

【问题讨论】:

  • 你的变量是有意命名的urluri吗?
  • 如果您使用json.encode(...),您发送的不是 JSON 字符串。如果您希望将其视为 JSON,只需直接发送 { 'data': { 'xpto': '12345678901234567890' } }
  • @GünterZöchbauer 如果我这样做,会发生这种情况:E/flutter(1805):[ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] 未处理的异常:E/flutter( 1805):错误状态:无法设置内容类型为“application/json”的请求的正文字段。 E/flutter (1805): #0 Request.bodyFields= (package:http/src/request.dart:124:7) E/flutter (1805): #1 BaseClient._sendUnstreamed (package:http/src/base_client.dart :165:17) E/flutter (1805): E/flutter (1805): #2 BaseClient.post (package:http/src/base_client.dart:56:5) ...
  • 给了我这个错误:E/flutter (1805): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] 未处理的异常:E/flutter (1805): type ' _InternalLinkedHashMap' 不是类型转换中“String”类型的子类型,其中 E/flutter(1805):_InternalLinkedHashMap 来自 dart:collection E/flutter(1805):String 来自 dart:core E/flutter( 1805): 字符串来自 dart:core E/flutter (1805): 字符串来自 dart:core
  • “如果你使用 json.encode(...) 你发送一个字符串而不是 JSON”谢谢@GünterZöchbauer,我使用的是 json.encode(...),被删除了,现在我得到相应的响应!

标签: json post dart flutter


【解决方案1】:

这行得通!

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

Future<http.Response> postRequest () async {
  var url ='https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';

  Map data = {
    'apikey': '12345678901234567890'
  }
  //encode Map to JSON
  var body = json.encode(data);

  var response = await http.post(url,
      headers: {"Content-Type": "application/json"},
      body: body
  );
  print("${response.statusCode}");
  print("${response.body}");
  return response;
}

【讨论】:

  • 感谢您的示例!这在任何地方都有记录吗?在找到这个例子之前,我浪费了很多时间......:/
  • 它不起作用。内容类型标题将以“text/plain; charset=utf-8”结束
  • 必须将我的身体编码为 JSON 才能使其工作。但是很好的解决方案。谢谢。
  • flutter 中最新的 dart 现在支持 jsonEncode() 函数。谢谢。
  • 我遇到了这个问题,同时也允许在服务器上使用 CORS。导致 XMLHttpRequest 错误
【解决方案2】:

好的,终于有答案了……

您正确地指定了headers: {"Content-Type": "application/json"}, 来设置您的内容类型。在引擎盖下,包http 或较低级别的dart:io HttpClient 正在将其更改为application/json; charset=utf-8。但是,您的服务器 Web 应用程序显然不需要该后缀。

为了证明这一点,我在 Java 中进行了尝试,有两个版本

conn.setRequestProperty("content-type", "application/json; charset=utf-8"); // fails
conn.setRequestProperty("content-type", "application/json"); // works

您能否联系 Web 应用程序所有者解释他们的错误?我看不到 Dart 在哪里添加后缀,但我稍后会看。

编辑 后来的调查表明,它是http 包,虽然为你做了很多繁重的工作,但它正在添加你的服务器不喜欢的后缀。如果您不能让他们修复服务器,那么您可以绕过http 并直接使用dart:io HttpClient。您最终会得到一些样板文件,这些样板文件通常由 http 处理。

下面的工作示例:

import 'dart:convert';
import 'dart:io';
import 'dart:async';

main() async {
  String url =
      'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  Map map = {
    'data': {'apikey': '12345678901234567890'},
  };

  print(await apiRequest(url, map));
}

Future<String> apiRequest(String url, Map jsonMap) async {
  HttpClient httpClient = new HttpClient();
  HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
  request.headers.set('content-type', 'application/json');
  request.add(utf8.encode(json.encode(jsonMap)));
  HttpClientResponse response = await request.close();
  // todo - you should check the response.statusCode
  String reply = await response.transform(utf8.decoder).join();
  httpClient.close();
  return reply;
}

根据您的用例,重用 HttpClient 可能更有效,而不是为每个请求创建一个新的。 Todo - 添加一些错误处理;-)

【讨论】:

  • 我会尝试向老师报告,看看他是否有能力找到任何人来解决问题...非常感谢您的回答我会尝试找到如何管理这个aswel.. .再次非常感谢您花费的时间
  • @CláudioAlmeida 使用较低级别的HttpClient 使用工作版本更新了答案
  • Richard Heap 非常感谢它完美运行,再次感谢您花费的时间!它工作得很好,我会尝试让他们解决服务器上的字符集请求!你让我很开心,我被困在这里 3 天,我失去了动力! tyvm
  • @RichardHeap 感谢您的帮助。我在使用常规 http 包发送带有嵌套 json 对象的 put 请求时遇到了麻烦,使用 HttpClient 类解决了它。
  • 我遇到了这个问题,同时也允许在服务器上使用 CORS。导致 XMLHttpRequest 错误
【解决方案3】:

这也可以:

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

  sendRequest() async {

    Map data = {
       'apikey': '12345678901234567890'
    };

    var url = 'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
    http.post(url, body: data)
        .then((response) {
      print("Response status: ${response.statusCode}");
      print("Response body: ${response.body}");
    });  
  }

【讨论】:

  • 这不仅有效,还清楚地表明大多数时候您不需要对数据进行 json 编码,谢谢!
  • 对我不起作用:状态不佳:无法设置内容类型为“application/json”的请求的正文字段。
【解决方案4】:

这对我有用

String body = json.encode(parameters);

http.Response response = await http.post(
  url: 'https://example.com',
  headers: {"Content-Type": "application/json"},
  body: body,
);

【讨论】:

    【解决方案5】:

    我认为很多人对 Post 'Content-type': 'application / json' 有疑问 这里的问题是将数据Map &lt;String, dynamic&gt;解析为json

    希望下面的代码可以帮助别人

    型号:

    class ConversationReq {
      String name = '';
      String description = '';
      String privacy = '';
      String type = '';
      String status = '';
    
      String role;
      List<String> members;
      String conversationType = '';
    
      ConversationReq({this.type, this.name, this.status, this.description, this.privacy, this.conversationType, this.role, this.members});
    
      Map<String, dynamic> toJson() {
    
        final Map<String, dynamic> data = new Map<String, dynamic>();
    
        data['name'] = this.name;
        data['description'] = this.description;
        data['privacy'] = this.privacy;
        data['type'] = this.type;
    
        data['conversations'] = [
          {
            "members": members,
            "conversationType": conversationType,
          }
        ];
    
        return data;
      }
    }
    

    请求:

    createNewConversation(ConversationReq param) async {
        HeaderRequestAuth headerAuth = await getAuthHeader();
        var headerRequest = headerAuth.toJson();
    /*
    {
                'Content-type': 'application/json',
                'x-credential-session-token': xSectionToken,
                'x-user-org-uuid': xOrg,
              }
    */
    
        var bodyValue = param.toJson();
    
        var bodydata = json.encode(bodyValue);// important
        print(bodydata);
    
        final response = await http.post(env.BASE_API_URL + "xxx", headers: headerRequest, body: bodydata);
    
        print(json.decode(response.body));
        if (response.statusCode == 200) {
          // TODO
        } else {
          // If that response was not OK, throw an error.
          throw Exception('Failed to load ConversationRepo');
        }
      }
    

    【讨论】:

      【解决方案6】:

      我是这样实现的:

      static createUserWithEmail(String username, String email, String password) async{
          var url = 'http://www.yourbackend.com/'+ "users";
          var body = {
              'user' : {
                'username': username,
                'address': email,
                'password': password
             }
          };
      
          return http.post(
            url, 
            body: json.encode(body),
            headers: {
              "Content-Type": "application/json"
            },
            encoding: Encoding.getByName("utf-8")
          );
        }
      

      【讨论】:

      • 谢谢,我实现了“encoding: E​​ncoding.getByName("utf-8")”并解决了我的问题
      【解决方案7】:

      这个是为了使用 HTTPClient 类

       request.headers.add("body", json.encode(map));
      

      我将编码的 json 正文数据附加到标头并添加到其中。它对我有用。

      【讨论】:

        【解决方案8】:

        在我的情况下,Flutter App 中的 POST 可以在 Web 上运行,但不能在 Android 设备或模拟器上运行。

        Flutter->服务器->API

        为了修复它,我:

        1. 更改了服务器上的 HTTP HEADER:

          $curlArr[CURLOPT_HTTPHEADER] = str_replace("application/x-www-form-urlencoded; charset=utf-8",
            "application/x-www-form-urlencoded",$curlArr[CURLOPT_HTTPHEADER]);
          
        2. 将大部分标头从邮递员那里复制到我的应用程序中。

        【讨论】:

          【解决方案9】:
          String body = json.encode(parameters);
          
          http.Response response = await http.post(
            url: Uri.parse('https://example.com'),
            headers: {"Content-Type": "application/json"},
            body: body,
          );
          

          这对我有用!

          【讨论】:

            【解决方案10】:

            就我而言,我忘了启用

            app.use(express.json());
            

            在我的 NodeJs 服务器中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-07-03
              • 2020-01-18
              • 1970-01-01
              • 2016-03-12
              • 1970-01-01
              • 2017-01-19
              • 2012-02-23
              • 1970-01-01
              相关资源
              最近更新 更多