我无法创建一个内部有另一个地图的地图。

问题描述 投票:0回答:1
import 'package:flutter/foundation.dart';
import 'package:clubinn/services/network_helper.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

String userToJson(Models data) => json.encode(data.toJson());

class Models {

  String url = 'http://localhost:3000';

  String name;
  String email;
  String password;
  LocationJson location;
  String DOB;
  String gender;
  String mobile;
  String type;
  List<double> coordinates;

  Models(
    {
      @required this.email,
      @required this.password,
    }
  );

  Future<http.Response> loginDataToJson() async{
    Map body =  {
      "email": email,
      "password": password
    };

    NetworkHelper networkHelper = new NetworkHelper(
      '$url/user/login',
    );
    http.Response response = await networkHelper.postData(body);
    //dynamic decodedData = jsonDecode(response.body);
    return response;
  }

  Models.signUp(
    {
      @required this.name,
      @required this.email,
      @required this.password,
      @required this.location,
      @required this.DOB,
      @required this.gender,
      @required this.mobile
    }
  );


  Future<http.Response> createUser() async{
    Map<String, dynamic> body = {
      "name": name,
      "email": email,
      "password": password,
      "birthday": DOB,
      "gender": gender,
      "location": location.toJson(),
      "phone_number": mobile
    };

    NetworkHelper networkHelper = new NetworkHelper(
      '$url/user/signup',
    );
    http.Response response = await networkHelper.postData(body);

    return response;
  }

}

class LocationJson {
  String type;
  List<double> coordinates;

  LocationJson({
    this.type,
    this.coordinates,
  });


  Map<String,dynamic> toJson() => {
    "type": type,
    "coordinates": List<double>.from(coordinates.map((x) => x)),
  };

}

下面给出了注册页面的代码。

class _SignUpPageState extends State<SignUpPage> {

  final dateFormat = DateFormat('MM-dd-yyyy');

  String name;
  String email;
  String DOB;
  String password;
  String mobileNumber;
  List<double> coordinates = [];
  Location location = Location();
  List<String> genderList = ['Male', 'Female', 'Others'];
  String selectedGender = 'Male';
  var locationTextController = new TextEditingController();

  DropdownButton<String> androidDropdown() {
    List<DropdownMenuItem<String>> genderDropdown = [];
    for(String gender in genderList) {
      var newItem = DropdownMenuItem(
        child: Text(
          gender,
          style: TextStyle(
            fontFamily: 'Montserrat',
            fontWeight: FontWeight.bold,
            color: Color(0xFFDDB911),
          ),
        ),
        value: gender,
      );
      genderDropdown.add(newItem);
    }
    return DropdownButton<String>(
      value: selectedGender,
      items: genderDropdown,
      onChanged: (value) {
        selectedGender = value;
      },
    );
  }

  CupertinoPicker iOSPicker() {
    List<Text> pickerItems = [];

    for(String gender in genderList) {
      pickerItems.add(
        Text(
          gender,
          style: TextStyle(
            fontFamily: 'Montserrat',
            fontWeight: FontWeight.bold,
            color: Color(0xFFDDB911),
          ),
        ),
      );
    }

    return CupertinoPicker(
      backgroundColor: Color(0xFF101010),
      itemExtent: 32.0,
      onSelectedItemChanged: (selectedIndex) {
        selectedGender = genderList[selectedIndex];
      },
      children: pickerItems,
    );
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              SizedBox(height: 5.0),
              Align(
                alignment: Alignment.topLeft,
                child: FlatButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  child: Icon(
                    Icons.arrow_back_ios,
                    size: 50.0,
                    color: Color(0xFFDDB911),
                  ),
                ),
              ),
              Container(
                padding: EdgeInsets.only(top: 50.0, left: 20.0, right: 20.0),
                child: Column(
                  children: <Widget>[
                    TextField(
                      onChanged: (value) {
                        name = value;
                      },
                      decoration: InputDecoration(
                        labelText: 'NAME',
                        labelStyle: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.bold,
                          color: Colors.grey,
                        ),
                        focusedBorder: UnderlineInputBorder(
                            borderSide: BorderSide(color: Color(0xFFDDB911)),
                        ),
                      ),
                    ),
                    SizedBox(height: kSizedBoxHeight),
                    TextField(
                      onChanged: (value) {
                        email = value;
                      },
                      decoration: InputDecoration(
                        labelText: 'EMAIL',
                        labelStyle: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.bold,
                          color: Colors.grey,
                        ),
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFFDDB911)),
                        ),
                      ),
                    ),
                    SizedBox(height: kSizedBoxHeight),
                    TextField(
                      onChanged: (value) {
                        password = value;
                      },
                      decoration: InputDecoration(
                        labelText: 'PASSWORD',
                        labelStyle: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.bold,
                          color: Colors.grey,
                        ),
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFFDDB911)),
                        ),
                      ),
                      obscureText: true,
                    ),
                    SizedBox(height: kSizedBoxHeight),
                    TextField(
                      onChanged: (value) {
                        mobileNumber = value;
                      },
                      decoration: InputDecoration(
                        labelText: 'MOBILE NUMBER',
                        labelStyle: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.bold,
                          color: Colors.grey,
                        ),
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFFDDB911)),
                        ),
                      ),
                    ),
                    SizedBox(height: kSizedBoxHeight),
                    Row(
                      children: <Widget>[
                        Expanded(
                          flex: 6,
                          child: TextField(
                            controller: locationTextController,
                            decoration: InputDecoration(
                              labelText: 'ADDRESS',
                              labelStyle: TextStyle(
                                fontFamily: 'Montserrat',
                                fontWeight: FontWeight.bold,
                                color: Colors.grey,
                              ),
                              focusedBorder: UnderlineInputBorder(
                                borderSide: BorderSide(color: Color(0xFFDDB911)),
                              ),
                            ),
                          ),
                        ),
                        SizedBox(width: 15.0),
                        Expanded(
                          flex: 1,
                          child: GestureDetector(
                            onTap: () async {
                              await location.getCurrentLocation();
                              coordinates = [location.latitude, location.longitude];
                              setState(() {
                                locationTextController.text = 'Lat: ${location.latitude}, Long: ${location.longitude}';
                              });
                            },
                            child: Shimmer.fromColors(
                              baseColor: Color(0xFFDDB911),
                              highlightColor: Color(0xFFFFFF99),
                              child: Icon(
                                Icons.my_location,
                                size: 50.0,
                                //color: Color(0xFFDDB911),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: kSizedBoxHeight),
                    DateTimeField(
                      onChanged: (value) {
                        var currentDate = DateTime.now();
                        if(value == null) {
                          value = DateTime.now();
                        } else if(currentDate.difference(value).inDays < 6575) {

                        } else {
                          String dateWithTime = value.toString();
                          DOB = convertDateTimeDisplay(dateWithTime);
                          //print(DOB);
                        }
                      },
                      format: dateFormat,
                      decoration: InputDecoration(
                        labelText: 'DOB',
                        labelStyle: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.bold,
                          color: Colors.grey,
                        ),
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFFDDB911)),
                        ),
                      ),
                      onShowPicker: (context, currentValue) {
                        return showDatePicker(
                            context: context,
                            firstDate: DateTime(1900),
                            initialDate: currentValue ?? DateTime.now(),
                            lastDate: DateTime.now()
                        );
                      },
                    ),
                    SizedBox(height: 36.0),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          'GENDER',
                          style:  TextStyle(
                            fontFamily: 'Montserrat',
                            fontWeight: FontWeight.bold,
                            fontSize: 16.0,
                            color: Colors.grey,
                          ),
                        ),
                        Container(
                          height: 40.0,
                          alignment: Alignment.center,
                          color: Color(0xFF101010),
                          child: Platform.isIOS ? iOSPicker() : androidDropdown(),
                        ),
                      ],
                    ),
                    SizedBox(height: 40.0),
                    Container(
                        height: 50.0,
                        child: GestureDetector(
                          onTap: () async {
                            Models userData = new Models.signUp(
                                name: name,
                                email: email,
                                password: password,
                                location: LocationJson(type: 'Point', coordinates: coordinates),
                                DOB: DOB,
                                gender: selectedGender,
                                mobile: mobileNumber
                            );
                            http.Response response = await userData.createUser();
                            print(response);
                          },
                          child: Material(
                            borderRadius: BorderRadius.circular(20.0),
                            shadowColor: Color(0xFFFFFF99),
                            color: Color(0xFFDDB911),
                            elevation: 7.0,
                            child: Center(
                              child: Text(
                                'SIGNUP',
                                style: TextStyle(
                                    color: Color(0xFFEFEFEF),
                                    fontSize: 17.0,
                                    fontWeight: FontWeight.bold,
                                    fontFamily: 'Montserrat'
                                ),
                              ),
                            ),
                          ),
                        ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

我试图创建一个注册模型并将其发送到我的API中 但 "位置 "键有另一个mapjsonobject,包含一个 "类型": "point "和 "coordinates": [双,双]。

最终的json对象应该是这样的

{
    "name": "Arsh Bansal",
    "email": "[email protected]",
    "password": "123456789",
    "birthday": "06-21-2000",
    "gender": "Male",
    "location": {
        "type": "Point", 
        "coordinates": [13.0987, 88.403]
    },
    "phone_number": "123456789"
}

网络助手代码如下。

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

class NetworkHelper {

  NetworkHelper(this.url);
  NetworkHelper.withHeader(this.url, this.headers);

  final String url;
  Map<String, String> headers;

  Future getData() async {

    http.Response response = await http.get(url);

    if(response.statusCode == 200) {
      String data = response.body;

      return jsonDecode(data);
    } else {
      String error = response.body;

    }
  }

  Future<http.Response> postData(Map body) async {

    http.Response response = await http.post(url, headers: headers, body: body);
    return response;

  }

}

但我得到了以下的错误信息

我得到的错误是:Unhandled Exception: type '_InternalLinkedHashMap>' is not a subtype of type 'String' in type cast----------。

#0      CastMap.forEach.<anonymous closure> (dart:_internal/cast.dart:288:25)
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:379:8)
#2      CastMap.forEach (dart:_internal/cast.dart:287:13)
#3      mapToQuery (package:http/src/utils.dart:17:7)
#4      Request.bodyFields= (package:http/src/request.dart:137:12)
#5      BaseClient._sendUnstreamed (package:http/src/base_client.dart:170:17)
#6      BaseClient.post (package:http/src/base_client.dart:58:7)
#7      post.<anonymous closure> (package:http/http.dart:70:16)
#8      _withClient (package:http/http.dart:166:20)
#9      post (package:http/http.dart:69:5)
#10     NetworkHelper.postData (package:clubinn/services/network_helper.dart:28:36)
#11     Models.createUser (package:clubinn/models/models.dart:72:50)
#12     _SignUpPageState.build.<anonymous closure> (package:clubinn/sc<…>
json http flutter dart maps
1个回答
0
投票

你的问题是使用了 http.postbody 参数。如果你阅读文档可以看到它的描述是。

body设置请求的主体。它可以是一个String,一个List或者一个Map。如果是一个字符串,就会使用编码并作为请求的主体。请求的内容类型将默认为 "textplain"。

...

如果body是Map,则使用编码将其编码为表单字段。请求的内容类型将被设置为 "applicationx-www-form-urlencoded",不能被覆盖。

https:/pub.devdocumentationhttplatesthttppost.html)。

输入 body 你所给的是来自于下面的代码。

    Map<String, dynamic> body = {
      "name": name,
      "email": email,
      "password": password,
      "birthday": DOB,
      "gender": gender,
      "location": location.toJson(),
      "phone_number": mobile
    };

其中的类型都是不差钱的 Map<String, String> 由于例如位置都被赋予了 Map<String, dynamic> 作为价值。

  Map<String,dynamic> toJson() => {
    "type": type,
    "coordinates": List<double>.from(coordinates.map((x) => x)),
  };

而且,我认为你不想给... ... body 的地图。在之前提到的文档中可以看到,地图是 "使用编码作为表单字段进行编码的"。你正确的做法是将地图解析成一个JSON字符串,并将这个字符串作为主体给到 http.post.

所以正确的做法应该是这样的。

http.Response response = await http.post(url, headers: headers, body: json.encode(body));
© www.soinside.com 2019 - 2024. All rights reserved.