Recently I was working with some large JSON responses from an external service. I was parsing the JSON to a Map to work with it. For some internal needs, I needed the Map to be saved as text.

This is where I encountered a problem with IO.inspect and IO.puts. They both truncate large data structures in the console output. While this may be appreciated in general when dealing with large data, it makes the resulting text an invalid Map and loses data.

Example of the truncation or abbreviation:

%{
  "BusinessAddressDetailRecordsReturned" => "00",
  "OFACResult" => %{...},
  ...}

That excerpt is pulled directly from the printed output.

Turns out, there are some extra options with IO.inspect that can help with this.

large_map = MyApp.TestResponses.load_sample_response
IO.inspect(large_map, limit: :infinity)

The :limit option being set to :infinity prevents the truncation problem. It will write out the full Map as text.

There are some additional nice options available as well. Might be worth checking out.

https://hexdocs.pm/elixir/Inspect.Opts.html

2017-11-17 NOTE: A new option in Elixir 1.5.x is :printable_limit. The :printable_limit option applies to strings and charlists while :limit does not. This is helpful when trying to inspect a large string. The value is specified in bytes. It also supports the atom :infinity.

large_string = MyApp.TestResponses.load_sample_text_file
IO.inspect(large_string, printable_limit: 8192)
IO.inspect(large_string, printable_limit: :infinity)

2018-03-12 NOTE: If you’ve ever seen IEx output single-quote letters when you expected to see a list of numbers, this is the behavior you are encountering.

In short, Erlang expresses strings as a list of chars. So, when IEx sees a list of small integers, it assumes it’s a single-quoted string and converts it to the ASCII characters for display.

Try it yourself:

iex> IO.inspect [65, 66, 67]
'ABC'

When the list includes an integer that doesn’t match to an ASCII character, it won’t do that. This can make it confusing because it feels inconsistent.

iex> IO.inspect [65, 66, 67, 1000]
[65, 66, 67, 1000]

You can force IO.inspect to not do this with the charlists option:

iex> IO.inspect [65, 66, 67], charlists: :as_lists
[65, 66, 67]

With Elixir 1.6.x, it uses a boolean false like this…

iex> IO.inspect [65, 66, 67], charlists: false
[65, 66, 67]