Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why dart:convert :: json.encoder turns everything into a string?

I am trying to send an HTTP PUT request to FastAPI backend from flutter code. I jsonify the data before I put into the request body. Here are my data classes:

class ListeningHistory {
  final String userId;
  List<BareMinPost> podcasts;

  ListeningHistory({required this.userId, required this.podcasts});

  Map<String, dynamic> toJson() {
    podcasts = []; // for simplicity's sake
    return {'user_id': userId, 'podcasts': jsonEncode(podcasts)};
  }

Please note that I intentionally replaced the actual podcasts with an empty array above for the sake of simplicity for this example.

class BareMinPost {
  final String title;
  final String publishedDate;
  final int pausedAt;

  BareMinPost({
    required this.title,
    required this.publishedDate,
    required this.pausedAt,
  });

  BareMinPost.fromJson(Map<String, dynamic> json)
      : title = json['title'] as String,
        publishedDate = json['publishedDate'] as String,
        pausedAt = json['pausedAt'] as int;

  Map<String, dynamic> toJson() =>
      {'title': title, 'publishedDate': publishedDate, 'pausedAt': pausedAt};

  @override
  String toString() {
    return "BareMinPost - title: $title   publishedDate: $publishedDate   puasedAt: $pausedAt";
  }
}

I use the following piece of code to json encode the data:

    import 'dart:convert';
...
    ListeningHistory hist = ListeningHistory(
        userId: "$userId", podcasts: previouslyListenedTo);
    String reqBody = json.encode(hist);
    dualLog(logger, '------------------->>>>-----$reqBody');

log line prints out as follows:

------------------->>>>-----{"user_id":"org.couchdb.users:alp","podcasts":"[]"}

Please note the double quotes around the array at the end. These, I believe should not be there but they are for some reason.

And eventually when I send this request the fastapi server, it complains as follows:

ERROR: {"detail":[{"type":"list_type","loc":["body","podcasts"],"msg":"Input should be a valid list","input":"[]"}]}

What am I missing here ?

like image 218
newbie Avatar asked Sep 03 '25 03:09

newbie


1 Answers

I expanded the comment and included an example:

import 'dart:convert' show JsonUnsupportedObjectError, jsonEncode, jsonDecode;

class BareMinPost {
  BareMinPost({required this.title});
  final String title;

  Map<String, dynamic> toJson() => {'title': title};

  factory BareMinPost.fromJson(Map<String, dynamic> json) {
    // Validate input
    if (json
        case {
          'title': String title,
        }) {
      return BareMinPost(title: title);
    } else {
      throw JsonUnsupportedObjectError(json,
          cause: 'BareMinPost: Json validation failed');
    }
  }
}

class ListeningHistory {
  final String userId;
  List<BareMinPost> podcasts;

  ListeningHistory({required this.userId, required this.podcasts});

  Map<String, dynamic> toJson() {
    return {
      'user_id': userId,
      'podcasts': podcasts
          .map(
            (e) => e.toJson(),
          )
          .toList()
    };
  }

  factory ListeningHistory.fromJson(Map<String, dynamic> json) {
    // Validate input
    if (json
        case {
          'user_id': String userId,
          'podcasts': List podcasts,
        }) {
      return ListeningHistory(
        userId: userId,
        podcasts: podcasts.map((e) => BareMinPost.fromJson(e)).toList(),
      );
    } else {
      throw JsonUnsupportedObjectError(json,
          cause: 'ListeningHistory: Json validation failed');
    }
  }
}

Usage:

void main(List<String> args) {
  final history = ListeningHistory(userId: 'json1997', podcasts: [
    BareMinPost(title: 'Song A'),
    BareMinPost(title: 'Song B'),
  ]);

  // Encoding
  print('Encoding: ...');
  print(
    history.toJson(),
  ); // Prints: {user_id: json1997, podcasts: [{title: Song A}, {title: Song B}]}
  final jsonString = jsonEncode(history.toJson());
  print(
    jsonString,
  ); // Prints: {"user_id":"json1997","podcasts":[{"title":"Song A"},{"title":"Song B"}]}

  // Decoding
  print('\nDecoding ...');
  final jsonMap = jsonDecode(jsonString);
  print(jsonMap);
  final historyClone = ListeningHistory.fromJson(jsonMap);
}

The console output is listed below:

Encoding: ...
{user_id: json1997, podcasts: [{title: Song A}, {title: Song B}]}
{"user_id":"json1997","podcasts":[{"title":"Song A"},{"title":"Song B"}]}

Decoding ...
{user_id: json1997, podcasts: [{title: Song A}, {title: Song B}]}
like image 194
Dan R Avatar answered Sep 05 '25 01:09

Dan R