【问题标题】:How to parse a complex(nested) object to JSON and send it to server using HTTP in flutter?如何将复杂(嵌套)对象解析为 JSON 并在 Flutter 中使用 HTTP 将其发送到服务器?
【发布时间】:2019-12-30 21:35:35
【问题描述】:

您好,我有一个类,其中嵌套了其他类。我想将此对象转换为 JSON 字符串并将其发送到服务器。

我已经从堆栈溢出和谷歌搜索中尝试了很多答案。不足以回答我的问题。

感谢任何帮助。

这是我的模型

class Place {
   String name;
   String description;
   List<PhoneNumber> phoneNumbers;
   List<String> tags;
   GPSCoordinante gpsCoordinates;
   List<Service> services;
   List<Album> albums;
   SocialMedia socialMedia;
   List<Comment> comments;
   List<String> imageURLArray;
   int rating;
   int shares;
   int favorites;
   int views;
   String category;
   String subcategory;
   WorkingHour workingHours;
   bool deleted;
   double distanceToUser;
   bool isApproved;
   String address;
   List<String> coverImages;

  Place({
    this.name,
    this.description,
    this.phoneNumbers,
    this.tags,
    this.gpsCoordinates,
    this.services,
    this.albums,
    this.socialMedia,
    this.comments,
    this.imageURLArray,
    this.rating,
    this.shares,
    this.favorites,
    this.views,
    this.category,
    this.subcategory,
    this.workingHours,
    this.deleted,
    this.distanceToUser,
    this.isApproved ,
    this.address,
    this.coverImages,
});

  factory Place.fromJson(Map<String, dynamic> json) {


    List phoneNumbersJsonList = json['phoneNumbers'] as List;
    List<PhoneNumber> parsedPhoneNumbers = phoneNumbersJsonList.map((value) => PhoneNumber.fromJson(value)).toList();

    List servicesJsonList = json['services'] as List;
    List<Service> parsedServices = servicesJsonList.map((value) => Service.fromJson(value)).toList();

    List walbumsJsonList = json['albums'] as List;
    List<Album> parsedAlbums = walbumsJsonList.map((value) => Album.fromJson(value)).toList();

    List commentsJsonList = json['comments'] as List;
    List<Comment> parsedComments = commentsJsonList.map((value) => Comment.fromJson(value)).toList();


    return Place(
        name: json['name'],
        description: json['description'],
        phoneNumbers:  parsedPhoneNumbers,
        gpsCoordinates: json['gpsCoordinates'],
        services: parsedServices,
        albums: parsedAlbums,
        socialMedia: json['socialMedia'],
        comments: parsedComments,
        imageURLArray: json['imageURLArray'],
        rating: json['rating'],
        shares : json['shares'],
        favorites: json['favorites'],
        category: json['category'],
        subcategory: json['subcategory'],
        workingHours: json['workingHours'],
        deleted: json['deleted'],
        isApproved: json['isApproved'],
        address: json['address'],
        coverImages: json['coverImages'],
    );

  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["name"] = name;
     map["description"] = description;
     map["services"] = services;
     map["albums"] = albums;
     map["comments"] = comments;
     map["imageURLArray"] = imageURLArray;
     map["rating"] = rating;
     map["shares"] = shares;
     map["favorites"] = favorites;
     map["category"] = category;
     map["subcategory"] = subcategory;
     map["workingHours"] = workingHours;
     map["deleted"] = deleted;
     map["isApproved"] = isApproved;
     map["address"] = address;
     map["coverImages"] = coverImages;


     return map;
   }


}

class PhoneNumber {
   int phoneNumber;
   String owner;

  PhoneNumber({
    this.phoneNumber,
    this.owner
});

  factory PhoneNumber.fromJson(Map<String, dynamic> json) {
    return PhoneNumber(
      phoneNumber: json['phoneNumber'],
      owner: json['owner'],
    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["phoneNumber"] = phoneNumber;
     map["owner"] = owner;

     return map;
   }
}

class GPSCoordinante {
   double longitude;
   double latitude;

  GPSCoordinante({
    this.longitude,
    this.latitude
});

  factory GPSCoordinante.fromJson(Map<String, dynamic> json) {
    return GPSCoordinante(
      longitude: json['longitude'],
      latitude: json['latitude'],
    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["longitude"] = longitude;
     map["latitude"] = latitude;

     return map;
   }
}


class Service {

  String name;
  String description;

  Service({
    this.name,
    this.description
  });

  factory Service.fromJson(Map<String, dynamic> json) {
    return Service(
      name: json['name'],
      description: json['description'],
    );
  }

  Map toMap() {
    var map = new Map<String, dynamic>();
    map["name"] = name;
    map["description"] = description;

    return map;
  }
}

class Album {
   String name;
   String nameEn;
   List<Item> items;
   bool isAutoConvertToUSDEnabled;
   bool isAllItemsDeliveryEnabled;

  Album({
    this.name,
    this.nameEn,
    this.items,
    this.isAutoConvertToUSDEnabled,
    this.isAllItemsDeliveryEnabled
});

  factory Album.fromJson(Map<String, dynamic> json) {

    List itemsJsonList = json['items'] as List;
    List<Item> parsedItems = itemsJsonList.map((value) => Item.fromJson(value)).toList();

    return Album(
      name: json['name'],
      nameEn: json['nameEn'],
      items: parsedItems,
      isAutoConvertToUSDEnabled: json['isAutoConvertToUSDEnabled'],
      isAllItemsDeliveryEnabled: json['isAllItemsDeliveryEnabled']

    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["name"] = name;
     map["nameEn"] = nameEn;
     map["items"] = items;
     map["isAutoConvertToUSDEnabled"] = isAutoConvertToUSDEnabled;
     map["isAllItemsDeliveryEnabled"] = isAllItemsDeliveryEnabled;

     return map;
   }
}

class Item{
   List<String> imageVariants;
   String name;
   String nameEn;
   bool isAutoConvertNameToEnglishEnabled;
   List<String> tags;
   int priceIQD;
   double priceUSD;
   String description;
   bool isDeliveryAvailable;
   bool isDinarAutomaticallyConvertedToDollar;
   int itemIndex;
   int albumIndex;
   bool isDeleted;

  Item({
    this.imageVariants,
    this.name,
    this.nameEn,
    this.isAutoConvertNameToEnglishEnabled,
    this.tags,
    this.priceIQD,
    this.priceUSD,
    this.description,
    this.isDeliveryAvailable,
    this.isDinarAutomaticallyConvertedToDollar,
    this.itemIndex,
    this.albumIndex,
    this.isDeleted
});

  factory Item.fromJson(Map<String, dynamic> json) {
    return Item(
      imageVariants: json['imageVariants'],
      name: json['name'],
      nameEn: json['nameEn'],
      isAutoConvertNameToEnglishEnabled: json['isAutoConvertNameToEnglishEnabled'],
      tags: json['tags'],
      priceIQD: json['priceIQD'],
      priceUSD: json['priceUSD'],
      description: json['description'],
      isDeliveryAvailable: json['isDeliveryAvailable'],
      isDinarAutomaticallyConvertedToDollar: json['isDinarAutomaticallyConvertedToDollar'],
      albumIndex: json['albumIndex'],
      itemIndex: json['itemIndex'],
      isDeleted: json['isDeleted'],

    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["imageVariants"] = imageVariants;
     map["name"] = name;
     map["nameEn"] = nameEn;
     map["isAutoConvertNameToEnglishEnabled"] = isAutoConvertNameToEnglishEnabled;
     map["tags"] = tags;
     map["priceIQD"] = priceIQD;
     map["priceUSD"] = priceUSD;
     map["description"] = description;
     map["isDeliveryAvailable"] = isDeliveryAvailable;
     map["isDinarAutomaticallyConvertedToDollar"] = isDinarAutomaticallyConvertedToDollar;
     map["albumIndex"] = albumIndex;
     map["itemIndex"] = itemIndex;
     map["isDeleted"] = isDeleted;

     return map;
   }

}


class Comment{
   String user;
   String userId;
   String text;
   DateTime dateTime;

  Comment({
   this.user,
   this.userId,
   this.text,
   this.dateTime
});

  factory Comment.fromJson(Map<String, dynamic> json) {
    return Comment(
      user: json['user'],
      userId: json['userId'],
      text: json['text'],
      dateTime: json['dateTime'],

    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["user"] = user;
     map["userId"] = userId;
     map["text"] = text;
     map["dateTime"] = dateTime;
     return map;
   }
}

class WorkingHour{
   String openingHour;
   String openingHourAmOrPm;
   String closingHour;
   String closingHourAmOrPm;

  WorkingHour({
    this.openingHour,
    this.openingHourAmOrPm,
    this.closingHour,
    this.closingHourAmOrPm
});

  factory WorkingHour.fromJson(Map<String, dynamic> json) {
    return WorkingHour(
      openingHour: json['openingHour'],
      openingHourAmOrPm: json['openingHourAmOrPm'],
      closingHour: json['closingHour'],
      closingHourAmOrPm: json['closingHourAmOrPm'],

    );
  }

   Map toMap() {
     var map = new Map<String, dynamic>();
     map["openingHour"] = openingHour;
     map["openingHourAmOrPm"] = openingHourAmOrPm;
     map["closingHour"] = closingHour;
     map["closingHourAmOrPm"] = closingHourAmOrPm;
     return map;
   }
}

class SocialMedia {
  String facebook ;
  String instagram;
  String youTube;
  String snapChat;
  String twitter;
  String googlePlus;
  String pinterest;

  SocialMedia({
    this.facebook,
    this.instagram,
    this.youTube,
    this.snapChat,
    this.twitter,
    this.googlePlus,
    this.pinterest
});

  factory SocialMedia.fromJson(Map<String, dynamic> json) {
    return SocialMedia(
      facebook: json['facebook'],
      instagram: json['instagram'],
      youTube: json['youTube'],
      snapChat: json['snapChat'],
      twitter: json['twitter'],
      googlePlus: json['googlePlus'],
      pinterest: json['pinterest'],


    );
  }

  Map toMap() {
    var map = new Map<String, dynamic>();
    map["facebook"] = facebook;
    map["instagram"] = instagram;
    map["youTube"] = youTube;
    map["twitter"] = twitter;
    map["snapChat"] = snapChat;
    map["googlePlus"] = googlePlus;
    map["pinterest"] = pinterest;

    return map;
  }
}

我正在尝试将此 Place 对象发送到服务器:

 Place place = Place(
      name: 'some name',
      description: 'some description',
      phoneNumbers: [PhoneNumber(phoneNumber: 125252525, owner: 'ali')],
      tags: ['some tag 2', 'some tag 2'],
      gpsCoordinates: GPSCoordinante(latitude: 11332, longitude: 13415),
      services: [Service(name: 'some service', description: 'some description')],
      albums: [
        Album(
            name: 'some album name',
            nameEn: 'someEN name',
            items: [
              Item(
                  name: 'some item name',
                  imageVariants: ['a;lgjlagj', 'ag;ja;gj;ag'],
                  nameEn: 'some en name',
                  isAutoConvertNameToEnglishEnabled: true,
                  tags: ['aggagag'],
                  priceIQD: 32425,
                  priceUSD: 252525,
                  description: 'agkgl;aj g;g ja;g ',
                  isDeliveryAvailable: true,
                  isDinarAutomaticallyConvertedToDollar: true,
                  itemIndex: 1,
                  albumIndex: 2)
            ],
            isAutoConvertToUSDEnabled: true,
            isAllItemsDeliveryEnabled: false)
      ],
      socialMedia: SocialMedia(facebook: 'facebook url'),
      comments: [
        Comment(
            user: 'some user',
            userId: '324-2-5-25',
            text: 'some comment',
            dateTime: DateTime.now())
      ],
      imageURLArray: ['some url'],
      rating: 0,
      shares: 0,
      favorites: 0,
      views: 0,
      category: 'sdagagasga;lgjaa;lgj',
      subcategory: 'as;glgjasl;gjas;lgkj',
      workingHours: WorkingHour(
          openingHour: '11', openingHourAmOrPm: 'am', closingHour: '11:00'),
      deleted: false,
      distanceToUser: 225252,
      isApproved: false,
      address: "some adress",
      coverImages: ['image one', 'image 2']);

我在使用json.encode(place) 时不断出错; 或json.encode(place.toMap()) 像这样

将对象转换为可编码对象失败:实例 “服务”

如何才能做到这一点?

【问题讨论】:

    标签: json http flutter dart encode


    【解决方案1】:

    您似乎不需要编写太多代码来将您的类编码和解码为 JSON 字符串。为了避免大量冗余并让您的生活更轻松,请使用以下解决方案:

    事情是这样的:

    首先在你的 pubspec.yaml 中依赖这些库:

    dependencies:
      # Your other regular dependencies here
      json_annotation: ^2.0.0
    
    dev_dependencies:
      # Your other dev_dependencies here
      build_runner: ^1.0.0
      json_serializable: ^2.0.0
    

    然后在您拥有所有模型类的文件中将其添加到顶部:

    import 'package:json_annotation/json_annotation.dart';
    part 'user.g.dart';
    

    而不是part 'user.g.dart'; 中的用户使用模型类所在文件的名称。在我的例子中是model.dart,所以它变成:

    part 'model.g.dart';
    

    这给出了一条红色波浪线:

    这很好,你需要做的是在项目根目录中的终端中运行以下命令:

    flutter pub run build_runner watch
    

    这样做是生成part 'model.g.dart'; 文件,这样您就不会再看到红色下划线了。 它会监视你的模型(包含你的模型的文件,在我的例子中是 models.dart 文件),看看你的类中的变量或字段是否有任何变化。

    如果您进行任何更改,它将自动重新生成将模型从 JSON 转换为 JSON 所需的代码,这意味着需要(json decode and encode)。

    然后,您必须将此行添加到模型文件(在我的例子中为 models.dart)中每个类的上方。

    所以把它添加到每个类上面的行:

    @JsonSerializable(explicitToJson: true)
    

    例如这样:

    @JsonSerializable(explicitToJson: true)
    class Place{ some fields};
    

    在你的类定义中,你必须将它添加到每个类中:

    factory Place.fromJson(Map<String, dynamic> json) => _$PlaceFromJson(json);
      Map<String, dynamic> toJson() => _$PlaceToJson(this);
    

    当然,您必须将变量 _$PlaceFromJson(json)_$PlaceToJson(this) 更改为反映您的班级名称的内容。例如,如果我有一个 PhoneNumber 类,我必须将这些两个变量分别更改为 _$PhoneNumberFromJson(json)_$PhoneNumberToJson(this)

    现在你只需要为你的模型创建一个对象,例如 Place 类,然后将它传递给 jsonEndcode 或 jsonDecode,如下所示:

    放置地点 = 地点( name : "某个名字", 描述:“一些描述” );

    var placeEncoded = jsonEncode(place);
    print(placeEncoded);
    
    var placeDecoded = jsonDecode(place);
    print(placeDecoded );
    

    这就是你需要做的。

    官方文档可以在这个页面上找到: https://flutter.dev/docs/development/data-and-backend/json#code-generation

    这是我的 model.dart 现在的样子:

    import 'package:json_annotation/json_annotation.dart';
    part 'models.g.dart';
    
    
    @JsonSerializable(explicitToJson: true)
    class Place {
       String name;
       String description;
       List<PhoneNumber> phoneNumbers;
       List<String> tags;
       GPSCoordinante gpsCoordinates;
       List<Service> services;
       List<Album> albums;
       SocialMedia socialMedia;
       List<Comment> comments;
       List<String> imageURLArray;
       int rating;
       int shares;
       int favorites;
       int views;
       String category;
       String subcategory;
       WorkingHour workingHours;
       bool deleted;
       double distanceToUser;
       bool isApproved;
       String address;
       List<String> coverImages;
    
      Place({
        this.name,
        this.description,
        this.phoneNumbers,
        this.tags,
        this.gpsCoordinates,
        this.services,
        this.albums,
        this.socialMedia,
        this.comments,
        this.imageURLArray,
        this.rating,
        this.shares,
        this.favorites,
        this.views,
        this.category,
        this.subcategory,
        this.workingHours,
        this.deleted,
        this.distanceToUser,
        this.isApproved ,
        this.address,
        this.coverImages,
    });
    
      factory Place.fromJson(Map<String, dynamic> json) => _$PlaceFromJson(json);
      Map<String, dynamic> toJson() => _$PlaceToJson(this);
    
    
    }
    
    @JsonSerializable(explicitToJson: true)
    class PhoneNumber {
       int phoneNumber;
       String owner;
    
      PhoneNumber({
        this.phoneNumber,
        this.owner
    });
    
    
       factory PhoneNumber.fromJson(Map<String, dynamic> json) => _$PhoneNumberFromJson(json);
       Map<String, dynamic> toJson() => _$PhoneNumberToJson(this);
    }
    
    @JsonSerializable(explicitToJson: true)
    class GPSCoordinante {
       double longitude;
       double latitude;
    
      GPSCoordinante({
        this.longitude,
        this.latitude
    });
    
       factory GPSCoordinante.fromJson(Map<String, dynamic> json) => _$GPSCoordinanteFromJson(json);
       Map<String, dynamic> toJson() => _$GPSCoordinanteToJson(this);
    
    }
    
    
    
    @JsonSerializable(explicitToJson: true)
    class Service {
    
      String name;
      String description;
    
      Service({
        this.name,
        this.description
      });
    
      factory Service.fromJson(Map<String, dynamic> json) => _$ServiceFromJson(json);
      Map<String, dynamic> toJson() => _$ServiceToJson(this);
    }
    
    @JsonSerializable(explicitToJson: true)
    class Album {
       String name;
       String nameEn;
       List<Item> items;
       bool isAutoConvertToUSDEnabled;
       bool isAllItemsDeliveryEnabled;
    
      Album({
        this.name,
        this.nameEn,
        this.items,
        this.isAutoConvertToUSDEnabled,
        this.isAllItemsDeliveryEnabled
    });
    
    
       factory Album.fromJson(Map<String, dynamic> json) => _$AlbumFromJson(json);
       Map<String, dynamic> toJson() => _$AlbumToJson(this);
    
    }
    
    @JsonSerializable(explicitToJson: true)
    class Item{
       List<String> imageVariants;
       String name;
       String nameEn;
       bool isAutoConvertNameToEnglishEnabled;
       List<String> tags;
       int priceIQD;
       double priceUSD;
       String description;
       bool isDeliveryAvailable;
       bool isDinarAutomaticallyConvertedToDollar;
       int itemIndex;
       int albumIndex;
       bool isDeleted;
    
      Item({
        this.imageVariants,
        this.name,
        this.nameEn,
        this.isAutoConvertNameToEnglishEnabled,
        this.tags,
        this.priceIQD,
        this.priceUSD,
        this.description,
        this.isDeliveryAvailable,
        this.isDinarAutomaticallyConvertedToDollar,
        this.itemIndex,
        this.albumIndex,
        this.isDeleted
    });
    
       factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
       Map<String, dynamic> toJson() => _$ItemToJson(this);
    
    }
    
    
    @JsonSerializable(explicitToJson: true)
    class Comment{
       String user;
       String userId;
       String text;
       DateTime dateTime;
    
      Comment({
       this.user,
       this.userId,
       this.text,
       this.dateTime
    });
    
       factory Comment.fromJson(Map<String, dynamic> json) => _$CommentFromJson(json);
       Map<String, dynamic> toJson() => _$CommentToJson(this);
    
    }
    
    @JsonSerializable(explicitToJson: true)
    class WorkingHour{
       String openingHour;
       String openingHourAmOrPm;
       String closingHour;
       String closingHourAmOrPm;
    
      WorkingHour({
        this.openingHour,
        this.openingHourAmOrPm,
        this.closingHour,
        this.closingHourAmOrPm
    });
    
       factory WorkingHour.fromJson(Map<String, dynamic> json) => _$WorkingHourFromJson(json);
       Map<String, dynamic> toJson() => _$WorkingHourToJson(this);
    
    }
    
    @JsonSerializable(explicitToJson: true)
    class SocialMedia {
      String facebook ;
      String instagram;
      String youTube;
      String snapChat;
      String twitter;
      String googlePlus;
      String pinterest;
    
      SocialMedia({
        this.facebook,
        this.instagram,
        this.youTube,
        this.snapChat,
        this.twitter,
        this.googlePlus,
        this.pinterest
    });
    
      factory SocialMedia.fromJson(Map<String, dynamic> json) => _$SocialMediaFromJson(json);
      Map<String, dynamic> toJson() => _$SocialMediaToJson(this);
    
    }
    

    当不必要的编码被丢弃并且不再使用时,我喜欢它。这就是我真正喜欢颤振的原因。

    保重。

    【讨论】:

    • explicitToJson: 是的,这就是我需要的。谢谢。
    【解决方案2】:

    您应该使用 BuiltValue 库 (https://github.com/google/built_value.dart)。

    在开始使用该技术之前,您需要学习一天的时间。

    但在简历中,您的课程将像上面的课程一样,您必须为每个复杂的课程创建一个类似的课程,例如 PhoneNumber,...:

    import 'package:built_collection/built_collection.dart';
    import 'package:built_value/built_value.dart';
    import 'package:built_value/serializer.dart';
    import 'package:wallet/models/transaction.dart';
    
    import 'json_serializer.dart';
    
    part 'place.g.dart';
    
    abstract class Place
        implements Built<Place, PlaceBuilder>, JsonSerializer {
    
    
      factory Place([PlaceBuilder updates(PlaceBuilder builder)]) =
          _$Place;
    
      Place._();
    
      factory Place.initState() {
        return Place((b) {
          b..name = "";
    
          return b;
        });
      }
      @nullable
      String get name;
    
      @nullable
      String get description;
    
      @nullable
      BuiltList<PhoneNumber> get phoneNumbers;
    
    
      static Serializer<Place> get serializer => _$place;
    
    
    }
    

    创建类之后,您必须定义一个 serializer.dart 类,您可以指定所有可以序列化的对象。请注意,对于定义中使用的每个 BuiltList,您必须为其创建一个工厂:

        part 'serializers.g.dart';
    
        @SerializersFor(<Type>[
          Place
        ])
        final Serializers serializers = (_$serializers.toBuilder()
              ..addPlugin(StandardJsonPlugin())
    ..addBuilderFactory(phoneNumberList.fullType, phoneNumberList.function)
            .build();
    
    ListBuilderFactory<PhoneNumber> phoneNumberList = ListBuilderFactory<PhoneNumber>();
    

    在最后一刻,您必须生成文件 .g.dart。使用以下命令:

    flutter packages pub run build_runner build --delete-conflicting-outputs
    

    最后,要解码项目中的 json,请调用:

    var body = jsonDecode(jsonPlaces);
            Place places = serializers.deserialize(
              body,
              specifiedType: const FullType(Place),
            );
    

    【讨论】:

    • 非常感谢 Roger 抽出宝贵时间撰写如此详细的答案。虽然我决定采用更简单的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多