Translating string representations of list into actual elixir list construct

I have a string representation of an elixir list. Is there any easy way to transform this string to a list without having to write my own parser?

E.g.

"[1,2,3,[4,5,6]]"

translated to elixir list

[1,2,3,[4,5,6]]

Before we try to help with the problem at hand, where do the string versions of the lists come from? If you can modify that code to not rely on such brittle serialization then you can use better format like Erlang terms or JSON.

1 Like

Unfortunately its a external input that i do not have control over. :frowning:

Alright then. Are you positive you’re only getting lists (and lists of lists) from that external source?

BTW here’s the nuclear option:

Code.eval_string/3

Only use this if your task is due yesterday.

You were warned. This way lay dragons and murderous magic. You’re much better off writing your own mini-parser.

2 Likes

I think here it is better to go with Code.string_to_quoted. If it is list of integers, it’ll return the same result as eval

3 Likes

When you say Elixir list, do you really just mean a list that can contain only numbers and other lists? If so you could simply use a JSON parser.

1 Like

In this specific case there is no need for that! Look that both List and Integer are literals in Elixir code. This mean their quoted representation is exactly the same, so:

iex> Code.string_to_quoted("[1,2,3,[4,5,6]]")
{:ok, [1, 2, 3, [4, 5, 6]]}

The same would work for other literals as well:

iex> Code.string_to_quoted(~s("abc"))
{:ok, "abc"}
iex> Code.string_to_quoted("1.5")    
{:ok, 1.5}
iex> Code.string_to_quoted("true")
{:ok, true}
iex> Code.string_to_quoted("nil") 
{:ok, nil}
iex> Code.string_to_quoted(":custom_atom")
{:ok, :custom_atom}
iex> Code.string_to_quoted("{:a, :tuple}")
{:ok, {:a, :tuple}}
iex> Code.string_to_quoted("[:a, :list]")
{:ok, [:a, :list]}

and even special forms:

iex> {:ok, {:%{}, _meta, data}} = Code.string_to_quoted("%{a: 5}")
{:ok, {:%{}, [line: 1], [a: 5]}}
iex> Map.new(data)
%{a: 5}

iex> {:ok, {:%, _, [aliases, {:%{}, _, data}]}} = Code.string_to_quoted("%Date{day: 1, month: 1, year: 2022}")
{:ok,
 {:%, [line: 1],
  [
    {:__aliases__, [line: 1], [:Date]},
    {:%{}, [line: 1], [day: 1, month: 1, year: 2022]}
  ]}}
iex> module = Macro.expand_literal(aliases, __ENV__)
Date
iex> struct(module, data)
~D[2022-01-01]
3 Likes

I’d probably stress the point again: How is the string representation created? This would inform how to best convert it back.

What will be in that list? Only numbers/strings or other types as well?

Its an output from Amazon Athena. So its output is like a tabular format. This example illustrates the nature of the data. It need not be just integers. They are all strings in a sense.

[foo=1, bar=bax, items={item_id=1, item_name=bar, item_qty=99}...]

OK, we’re getting somewhere. Is the data you’re showing us a result of an UNLOAD query?

Not really. Its an output from the query editor. Im expecting this has similar effects as UNLOAD. Even though it says cast as JSON the output is not JSON :frowning_face:

select cast(foo as JSON) 
FROM bar

I have solved my problem by doing

select 
foo.a
foo.b
foo.c
FROM bar