Rohan Kapur
Rohan Kapur

Reputation: 139

type 'int' is not a subtype of type 'double' -- Dart/Flutter Error

So I have an API set up that returns the following output on a specific endpoint when called:

{
    "total_user_currency": 0.1652169792,
    "total_sats": 2184,
    "total_btc": 0.00002184,
    "outputArray": [
        {
            "txid": "642fd534cb3a670a31f4d59e70452b133b0b461d871db44fcc91d32bb6b6f0cc",
            "vout": 2,
            "status": {
                "confirmed": true,
                "block_height": 625673,
                "block_hash": "0000000000000000000310649c075b9e2fed9b10df2b9f0831efc4291abcb7fb",
                "block_time": 1586732907
            },
            "value": 546
        },

    ]
}

And I'm using the following dart class to decode that JSON into an Object that I can interact with:

class UtxoData {
  final dynamic totalUserCurrency;
  final int satoshiBalance;
  final dynamic bitcoinBalance;
  List<UtxoObject> unspentOutputArray;

  UtxoData({this.totalUserCurrency, this.satoshiBalance, this.bitcoinBalance, this.unspentOutputArray});

  factory UtxoData.fromJson(Map<String, dynamic> json) {
    var outputList = json['outputArray'] as List;
    List<UtxoObject> utxoList = outputList.map((output) => UtxoObject.fromJson(output)).toList(); 

    return UtxoData(
      totalUserCurrency: json['total_user_currency'],
      satoshiBalance: json['total_sats'],
      bitcoinBalance: json['total_btc'],
      unspentOutputArray: utxoList
    );
  }
}

class UtxoObject {
  final String txid;
  final int vout;
  final Status status;
  final int value;

  UtxoObject({this.txid, this.vout, this.status, this.value});

  factory UtxoObject.fromJson(Map<String, dynamic> json) {
    return UtxoObject(
      txid: json['txid'],
      vout: json['vout'],
      status: Status.fromJson(json['status']),
      value: json['value']
    );
  }
}

class Status {
  final bool confirmed;
  final String blockHash;
  final int blockHeight;
  final int blockTime;

  Status({this.confirmed, this.blockHash, this.blockHeight, this.blockTime});

  factory Status.fromJson(Map<String, dynamic> json) {
    return Status(
      confirmed: json['confirmed'],
      blockHash: json['block_hash'],
      blockHeight: json['block_height'],
      blockTime: json['block_time']
    );
  }

}

Here is the function that actually calls the API in the code:

Future<UtxoData> fetchUtxoData() async {
    final requestBody = {
      "currency": "USD",
      "receivingAddresses": ["bc1q5jf6r77vhdd4t54xmzgls823g80pz9d9k73d2r"],
      "internalAndChangeAddressArray": ["bc1q5jf6r77vhdd4t54xmzgls823g80pz9d9k73d2r"]
    };

    final response = await http.post('https://thisisanexmapleapiurl.com', body: jsonEncode(requestBody), headers: {'Content-Type': 'application/json'} );

    if (response.statusCode == 200 || response.statusCode == 201) {
      notifyListeners();
      print(response.body);
      return UtxoData.fromJson(json.decode(response.body));
    } else {
      throw Exception('Something happened: ' + response.statusCode.toString() + response.body );
    }
  }

However, when I do run the function, I get the following error in my editor:

Exception has occurred.
_TypeError (type 'int' is not a subtype of type 'double')

I get it on the return UtxoData statement inside the factory method for the UtxoData class as shown below:

return UtxoData(
      totalUserCurrency: json['total_user_currency'],
      satoshiBalance: json['total_sats'],                    <<<<============= The exception pops up right there for some reason
      bitcoinBalance: json['total_btc'],
      unspentOutputArray: utxoList
    );

This is strange because I know that the API is returning an int there. totalUserCurrency and bitcoinBalance have to be dynamic because they can either be 0 (an int) or an arbitrary number like 12942.3232 (a double).

Why do I get this error and how can I correct this? Much appreciated

Upvotes: 0

Views: 3901

Answers (2)

Francisco Javier Snchez
Francisco Javier Snchez

Reputation: 1003

If you are parsing data, and you are unsure if it will be an Int or a double there are multiple solutions.

If you need an Int use parsedData.truncate() this works for both Int and double and it resolves into an Int by discarding decimals. Similarly you could also use cail() or floor() if you want the decimals to have some effect in the outcome.

So, in your case, you would only need to do like this:

satoshiBalance: json['total_sats'].truncate(),

I hope this helps!

Upvotes: 1

Sukhi
Sukhi

Reputation: 14215

I'd a similar problem where the amount I was getting from an API veried between 0 and few thousands including decimals. I tried the following :

this.balanceAmount = double.parse(json['total_balance']??'0.0'.toString());

This didn't work with my dataset. So, I enhanced it to the following which worked in all the cases for my dataset. You might need slight enhacement(s).

double parseAmount(dynamic dAmount){

    double returnAmount = 0.00;
    String strAmount;

    try {

      if (dAmount == null || dAmount == 0) return 0.0;

      strAmount = dAmount.toString();

      if (strAmount.contains('.')) {
        returnAmount = double.parse(strAmount);
      }  // Didn't need else since the input was either 0, an integer or a double
    } catch (e) {
      return 0.000;
    }

    return returnAmount;
  }

Upvotes: 2

Related Questions