Extracting an internal JSON object from another JSON object

659

Dart has no idea that your JSON structure will correspond to your object, or how. You can't directly cast the JSON (which is probably a Map<String, dynamic>, but could also be other things) to your objects. @betorcs answer is a start in the right direction but needs a bit more.

This line:

tweetExtendedEntities: json['extended_entities'] as TweetExtendedEntities,

Needs to be

tweetExtendedEntities: TweetExtendedEntities.fromJson['extended_entities'],

And your TweetExtendedEntities method should look more like this:

factory TweetExtendedEntities.fromJson(Map<String, dynamic> json) {
  return new TweetExtendedEntities(
      tweetMedia: createTweetMediaList(json['media']));
}

static List<TweetMedia> createTweetMediaList(List json) {
  if (json == null) return null;
  if (json.isEmpty) return [];

  return json.map((tweetMediaJson) => TweetMedia.fromJson(tweetMediaJson)).toList();
}

You could also certainly look into json_serializable if your needs start getting more complicated and you want to try to generate some of this code.

Share:
659
argamanza
Author by

argamanza

Updated on December 04, 2022

Comments

  • argamanza
    argamanza over 1 year

    I'm trying to show a list of tweets using Twitter API, using the fromJson factory.

    Each tweet object has an extended_entities object which is an array of media objects.

    If you're not familiar with the Twitter API you can see all the different objects here.

    Here are the models i created in order to achieve this:

    class Tweet {
      final String createdAt;
      final int id;
      final String idStr;
      final String text;
      final String inReplyToStatusIdStr;
      final String inReplyToUserIdStr;
      final TweetExtendedEntities tweetExtendedEntities;
    
      Tweet(
          {this.createdAt,
          this.id,
          this.idStr,
          this.text,
          this.inReplyToStatusIdStr,
          this.inReplyToUserIdStr,
          this.tweetExtendedEntities});
    
      factory Tweet.fromJson(Map<String, dynamic> json) {
        return new Tweet(
          createdAt: json['created_at'] as String,
          id: json['id'] as int,
          idStr: json['id_str'] as String,
          text: json['text'] as String,
          inReplyToStatusIdStr: json['in_reply_to_status_id_str'] as String,
          inReplyToUserIdStr: json['in_reply_to_user_id_str'] as String,
          tweetExtendedEntities: json['extended_entities'] as TweetExtendedEntities,
        );
      }
    }
    
    class TweetExtendedEntities {
      final List<TweetMedia> tweetMedia;
    
      TweetExtendedEntities({this.tweetMedia});
    
      factory TweetExtendedEntities.fromJson(Map<String, dynamic> json) {
        return new TweetExtendedEntities(
            tweetMedia: json['media'] as List<TweetMedia>);
      }
    }
    
    class TweetMedia {
      final String mediaType;
      final String mediaUrl;
    
      TweetMedia({this.mediaType, this.mediaUrl});
    
      factory TweetMedia.fromJson(Map<String, dynamic> json) {
        return new TweetMedia(
          mediaType: json['type'] as String,
          mediaUrl: json['media_url'] as String,
        );
      }
    }
    

    Before i tried to get the extended_entities object everything was fine and i successfully got the JSON data and parsed it, but when i try to get the media objects using the code above, i get this error:

    I/flutter (29538): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'TweetExtendedEntities' in type cast where
    I/flutter (29538):   _InternalLinkedHashMap is from dart:collection
    I/flutter (29538):   String is from dart:core
    I/flutter (29538):   TweetExtendedEntities is from package:pubg_companion/models/tweet.dart
    

    How can i get nested JSON objects using factory or any other way?

  • Dan Field
    Dan Field about 6 years
    OP also has to do something similar in TweetExtendedEntities.fromJson - can't cast it directly to a List<TweetMedia>. This answer would be a bit more helpful if it at least pointed out how that might work