Home > other >  'not a subtype' error when parsing Json for TypeAheadFormField Flutter
'not a subtype' error when parsing Json for TypeAheadFormField Flutter

Time:03-14

I am using TypeAheadFormField to show suggestions to the user as they type, with data pulled from an API designed to autosuggest items.

I have isolated the issue and it is failing at the suggestionsCallback: stage, as the call is made. I have isolated it to the API call and the parsing of the data. I have tried lots of variations in the Class, call etc but can't get the error to go on running.

The error showing under text field(on simulator)

enter image description here

My Class (leaned down Quicktype.io) I have tried lots of versions and none worked for me. I am just trying to get the address value from the List Items to get it working

class Items {
    Items({
        required this.items,
    });

    List<Item>? items;
    
    factory Items.fromJson(Map<String, dynamic> json) => Items(
        items: json["items"] == null ? null : List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
    );
}

class Item {
  final String address;

  const Item({
    required this.address,
  });

  static Item fromJson(Map<String, dynamic> json) => Item(
        address: json['address'],
      );
}

API returns in a Json List called Items (Have removed bulk of data for this example, just 'address' I want at the moment)

{"items":[{"title":"Buckingham Palace","address":{"label":"Buckingham Palace Road, London, SW1E 5, United Kingdom"}"title":"Buckingham Place, London, SW1E 6, United Kingdom","resultType":"street","address":{"label":"Buckingham Place, London, SW1E 6, United Kingdom"}...

My API call for the data

 class UserApi {
  static FutureOr<Iterable<Items>> getUserSuggestions(String query) async {

    final url = Uri.parse('https_call');
    final response = await http.get(url);

    if (response.statusCode == 200) {
      final users = json.decode(response.body);

   *Fails Here*   return users.map((json) => Items.fromJson(json)).where((user) {
        final nameLower = user.address.toLowerCase();
        final queryLower = query.toLowerCase();

        return nameLower.contains(queryLower);
      }).toList();
    } else {
      throw Exception();
    }
  }
}

Thank you

CodePudding user response:

I think that the json you provide us is incorrect.

I tried to fix it, so I made it like below:

{
    "items": [
        {
            "title": "Buckingham Palace",
            "address": {
                "label": "Buckingham Palace Road, London, SW1E 5, United Kingdom"
            },"title": "Buckingham Place, London, SW1E 6, United Kingdom",
            "resultType": "street",
            "address": {
                "label": "Buckingham Place, London, SW1E 6, United Kingdom"
            }
        }
    ]
}

And you can use the class below to parse it:

// To parse this JSON data, do
//
//     final items = itemsFromJson(jsonString);

import 'dart:convert';

Items itemsFromJson(String str) => Items.fromJson(json.decode(str));

String itemsToJson(Items data) => json.encode(data.toJson());

class Items {
    Items({
        this.items,
    });

    final List<Item> items;

    factory Items.fromJson(Map<String, dynamic> json) => Items(
        items: json["items"] == null ? null : List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "items": items == null ? null : List<dynamic>.from(items.map((x) => x.toJson())),
    };
}

class Item {
    Item({
        this.title,
        this.address,
        this.resultType,
    });

    final String title;
    final Address address;
    final String resultType;

    factory Item.fromJson(Map<String, dynamic> json) => Item(
        title: json["title"] == null ? null : json["title"],
        address: json["address"] == null ? null : Address.fromJson(json["address"]),
        resultType: json["resultType"] == null ? null : json["resultType"],
    );

    Map<String, dynamic> toJson() => {
        "title": title == null ? null : title,
        "address": address == null ? null : address.toJson(),
        "resultType": resultType == null ? null : resultType,
    };
}

class Address {
    Address({
        this.label,
    });

    final String label;

    factory Address.fromJson(Map<String, dynamic> json) => Address(
        label: json["label"] == null ? null : json["label"],
    );

    Map<String, dynamic> toJson() => {
        "label": label == null ? null : label,
    };
}

CodePudding user response:

Solution was to put

if (response.statusCode == 200) {
      Map<String, dynamic> users1 = json.decode(response.body);
      List<dynamic> users = users1["items"];

in place of

if (response.statusCode == 200) {
      final List users = json.decode(response.body);
  • Related