DEV Community

Phuc Tran
Phuc Tran

Posted on

Dart/Flutter — How to parse String to number

Dart extension methods

In this post, let’s learn a few methods to parse/convert String to number (integer, double or both).

1. Use parse() method (not recommended)

/// Parse string to integer
int stringToInt_parse(String input) {
  return int.parse(input, onError: (error) {
    // Return null if input string is invalid.
    // Change to default value if you want.
    return null;
});

/// Parse string to double
double stringToDouble_parse(String input) {
  return double.parse(input, (error) {
    // Return null if input string is invalid.
    // Change to default value if you want.
    return null;
  });
}

/// Parse string to number
num stringToNumber_parse(String input) {
  return num.parse(input, (error) {
    // Return null if input string is invalid.
    // Change to default value if you want.
    return null;
  });
}
Enter fullscreen mode Exit fullscreen mode

Test it

void main() {
  final testInt = '100';
  final testDouble = '100.1';
  final testInvalidNumber = 'a';

  print(stringToInt_parse(testInt)); // 100
  print(stringToDouble_parse(testInt)); // 100.0
  print(stringToNumber_parse(testInt)); // 100

  print(stringToInt_parse(testDouble)); // null
  print(stringToDouble_parse(testDouble)); // 100.1
  print(stringToNumber_parse(testDouble)); // 100.1

  print(stringToInt_parse(testInvalidNumber)); // null
  print(stringToDouble_parse(testInvalidNumber)); // null
  print(stringToNumber_parse(testInvalidNumber)); // null
}
Enter fullscreen mode Exit fullscreen mode

Notes:

  • We can use double.parse() to convert a valid integer string to int, but it will return a double (Line 7: 100.0). And obviously we can not convert a valid double string to integer, it will return null (Line 10: null).

  • With num.parse(), the program will try to parse to integer first, if it can not parse (get null), then it will try to parse to double. (That’s why at line 8, the output is 100 but not 100.0).

  • I don’t know exactly the reason behind this, but if you look at the signature of the int.parse(), double.parse() and num.parse(), you will see that onError is optional named parameter in int.parse() while with double.parse() and num.parse() it is optional positional parameter. 🤔 🤔 🤔

// Look at onError:
int.parse(input, onError: (error) {
  // ...
});

// No need onError: 
double.parse(input, (error) {
  // ...
});

// No need onError: 
num.parse(input, (error) {
  // ...
});
Enter fullscreen mode Exit fullscreen mode
  • If you don’t provide onError method to handle the exception with invalid string, the program will throw an exception at runtime.
/// Parse string to integer without handling error 
/// -> throw exception at runtime.
int stringToInt_parseWithoutErrorHandle(String input) {
  return int.parse(input);
}

void main() {
  final testInvalidNumber = 'a';
  print(stringToInt_parseWithoutErrorHandle(
   testInvalidNumber)
  );
}
Enter fullscreen mode Exit fullscreen mode

Exception:

Unhandled exception:
FormatException: Invalid radix-10 number (at character 1)
a
^

#0      int._throwFormatException (dart:core-patch/integers_patch.dart:131:5)
#1      int._parseRadix (dart:core-patch/integers_patch.dart:142:16)
#2      int._parse (dart:core-patch/integers_patch.dart:100:12)
#3      int.parse (dart:core-patch/integers_patch.dart:63:12)
#4      stringToInt_parseWithoutErrorHandle (package:dart/core/string/string_to_number.dart:58:14)
#5      main (package:dart/core/string/string_to_number.dart:18:9)
#6      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#7      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
Enter fullscreen mode Exit fullscreen mode
  • (Important) At the beginning, I highlighted that this parse() method is not recommended. The dart document says (source):
* ...
* The [onError] parameter is deprecated and will be removed.
* Instead of `int.parse(string, onError: (string) => ...)`,
* you should use `int.tryParse(string) ?? (...)`.
* ...
Enter fullscreen mode Exit fullscreen mode

As mentioned above, we should use tryParse() method instead. Let’s move to that method immediately.

2. Use tryParse() method

When using tryParse() method, we just need to provide the input String. In case the input is invalid, the program will return null. This is the difference between tryParse() and parse() (which throws exception if we don’t handle onError method).

int stringToInt_tryParse(String input) {
  return int.tryParse(input);
}

double stringToDouble_tryParse(String input) {
  return double.tryParse(input);
}

num stringToNumber_tryParse(String input) {
  return num.tryParse(input);
}
Enter fullscreen mode Exit fullscreen mode

Test it

void main() {
  final testInt = '100';
  final testDouble = '100.1';
  final testInvalidNumber = 'a';

  print(stringToInt_tryParse(testInt)); // 100
  print(stringToDouble_tryParse(testInt)); // 100.0
  print(stringToNumber_tryParse(testInt)); // 100

  print(stringToDouble_tryParse(testInt)); // 100.0
  print(stringToDouble_tryParse(testDouble)); // 100.1
  print(stringToNumber_tryParse(testDouble)); // 100.1

  print(stringToInt_tryParse(testInvalidNumber)); // null
  print(stringToDouble_tryParse(testInvalidNumber)); // null
  print(stringToNumber_tryParse(testInvalidNumber)); // null
}
Enter fullscreen mode Exit fullscreen mode

3. (Bonus) Use extension methods

In case you don’t know what extension methods is, it is a way to add more functions to existing libraries/classes. In our case, we use this technique to add 3 methods to String class.

extension StringExtension on String {
  int toInt() {
    return int.tryParse(this);
  }

  double toDouble() {
    return double.tryParse(this);
  }

  num toNumber() {
    return num.tryParse(this);
  }
}
Enter fullscreen mode Exit fullscreen mode

After creating above extension, now our String has 3 more methods that we can use as other exiting methods. So cool! 😎 😎 😎

void main() {
  final testInt = '100';
  final testDouble = '100.1';
  final testInvalidNumber = 'a';

  print(testInt.toInt()); // 100
  print(testInt.toDouble()); // 100.0
  print(testInt.toNumber()); // 100

  print(testDouble.toInt()); // null
  print(testDouble.toDouble()); // 100.1
  print(testDouble.toNumber()); // 100.1

  print(testInvalidNumber.toInt()); // null
  print(testInvalidNumber.toDouble()); // null
  print(testInvalidNumber.toNumber()); // null
}
Enter fullscreen mode Exit fullscreen mode

That’s it!
You can find original article on my blog.

Top comments (0)