1
votes

I'm dealing with a JSON API that returns a number as a string. For example "12", however, this field value could also be non-numeric, for example: "-".

I've parsed the JSON data into a map and I want to extract this field to as an integer in elixir, and then perform some operation depending on where the integer falls in a certain range.

There seem to be multiple ways to do this the two main being Integer.parse/1, which returns a tuple or :error, and String.to_integer/1, which returns the integer or raises an exception.

What is the best way to perform some operation based on where the numeric value contained inside a string falls in a certain range, handling parsing errors appropriately?

2

2 Answers

2
votes

If one expects the value can be not an integer (under normal, not exceptional circumstances,) one should use Integer.parse/2:

analysis =
  case Integer.parse(string_value_from_json) do
    {i, ""} when i in 1..10 ->
      "integer #{i} between 1 and 10"
    {i, ""} when i in 11..20 ->
      "integer #{i} is between 11 and 20"
    {i, ""} ->
      "integer #{i} was out of range"
    _ -> "integer could not be parsed"
  end

Throwing and handling an exception should be left as a last resort and is discouraged to be used to control a flow.

-1
votes

The documentation for Integer.parse says to use String.to_integer for this purpose, so it's probably best to follow the guidelines:

If you want to convert a string-formatted integer directly to a integer, String.to_integer/1 or String.to_integer/2 can be used instead.

However, String.to_integer raises an error if the string cannot be parsed. Error cases can be caught and assigned to nil, then the result pattern-matched over:

integer_value =
  try do
    String.to_integer(string_value_from_json)
  rescue
    _ -> nil
  end

analysis =
  case integer_value do
    nil -> "integer could not be parsed"
    integer_value when integer_value in 1..10 -> "integer #{integer_value} between 1 and 10"
    integer_value when integer_value in 11..20 -> "integer #{integer_value} is between 11 and 20"
    integer_value -> "integer #{integer_value} was out of range"
  end

IO.puts analysis