tovarchristian21

tovarchristian21

Hello guys, can you please help turn this map into a pure map. Some of the members of the map are still structs.

%{
  callback_query: nil,
  channel_post: nil,
  chosen_inline_result: nil,
  edited_message: nil,
  inline_query: nil,
  message: %Nadia.Model.Message{
    audio: nil,
    caption: nil,
    channel_chat_created: nil,
    chat: %Nadia.Model.Chat{
      first_name: "Christian",
      id: 543211234,
      last_name: "Tovar",
      photo: nil,
      title: nil,
      type: "private",
      username: "ChristianTovar"
    },
    contact: nil,
    date: 1562605521,
    delete_chat_photo: nil,
    document: nil,
    edit_date: nil,
    entities: nil,
    forward_date: nil,
    forward_from: nil,
    forward_from_chat: nil,
    from: %Nadia.Model.User{
      first_name: "Christian",
      id: 543211234,
      last_name: "Tovar",
      username: "ChristianTovar"
    },
    group_chat_created: nil,
    left_chat_member: nil,
    location: nil,
    message_id: 714,
    migrate_from_chat_id: nil,
    migrate_to_chat_id: nil,
    new_chat_member: nil,
    new_chat_photo: [],
    new_chat_title: nil,
    photo: [],
    pinned_message: nil,
    reply_to_message: nil,
    sticker: nil,
    supergroup_chat_created: nil,
    text: "google meets",
    venue: nil,
    video: nil,
    voice: nil
  },
  update_id: 412827321
}

Showing Posts 1 to 10

wolfiton

wolfiton

Hello,

Welcome to the forum

This may help you
from_struct(struct)View Source

from_struct(atom() | struct()) :: map()

Converts a struct to map.

It accepts the struct module or a struct itself and simply removes the __struct__ field from the given struct or from a new struct generated from the given module.

Example

defmodule User do
  defstruct [:name]
end

Map.from_struct(User)
#=> %{name: nil}

Map.from_struct(%User{name: "john"})
#=> %{name: "john"}
tovarchristian21

tovarchristian21 OP

I actually did that for the outer map. It was a struct, however that function does not turn inner struct into maps…

NobbZ

NobbZ

You need to implement the nesting on your own. But that is a lot more expensive, as it needs to reconstruct the maps from scratch

wolfiton

wolfiton

Wouldn’t s/he be able to use

variable_with_struct
|> Enum.each
|> Map.from_struct

Like this?

Also if i am mistaken please correct me(still learning to think in elixir and the language)

NobbZ

NobbZ

No, Enum.each/2 returns :ok. Also you need to decide for each key in the map/struct if you want to convert it or not.

Eiji

Eiji

Here is example working code:

# First of all minimal definition in order to make code compillable
defmodule Nadia.Model.Chat do
  defstruct [:first_name, :id, :last_name, :photo, :title, :type, :username]
end

defmodule Nadia.Model.User do
  defstruct [:first_name, :id, :last_name, :username]
end

defmodule Nadia.Model.Message do
  defstruct [
    :audio,
    :caption,
    :channel_chat_created,
    :chat,
    :contact,
    :date,
    :delete_chat_photo,
    :document,
    :edit_date,
    :entities,
    :forward_date,
    :forward_from,
    :forward_from_chat,
    :from,
    :group_chat_created,
    :left_chat_member,
    :location,
    :message_id,
    :migrate_from_chat_id,
    :migrate_to_chat_id,
    :new_chat_member,
    :new_chat_photo,
    :new_chat_title,
    :photo,
    :pinned_message,
    :reply_to_message,
    :sticker,
    :supergroup_chat_created,
    :text,
    :venue,
    :video,
    :voice
  ]
end

# Here is code which would work only for your specific case
defmodule Example do
  def sample(map) do
    message = ensure_map(map.message)
    chat = ensure_map(message.chat)
    from = ensure_map(message.from)
    updated_message = %{message | chat: chat, from: from}
    %{map | message: updated_message}
  end

  defp ensure_map(%{__struct__: _} = struct), do: Map.from_struct(struct)
  defp ensure_map(data), do: data
end

# Here is more dynamic way
# No matter how many maps and lists have you nested
# It will iterate over all map or list elements and finally ensure that they are not structs
# NOTE: If you want you can add extra guard to limit possible __struct__ value
# For example you probably do not want to create maps from Date, DateTime, NaiveDateTime and Time structs
defmodule ExampleDynamic do
  def sample(map), do: :maps.map(&do_sample/2, map)

  def do_sample(_key, value), do: ensure_nested_map(value)

  defp ensure_nested_map(list) when is_list(list), do: Enum.map(list, &ensure_nested_map/1)

  # NOTE: In pattern-matching order of function guards is important!
  # @structs [Date, DateTime, NaiveDateTime, Time]
  # defp ensure_nested_map(%{__struct__: struct} = data) when struct in @structs, do: data

  defp ensure_nested_map(%{__struct__: _} = struct) do
    map = Map.from_struct(struct)
    :maps.map(&do_sample/2, map)
  end

  defp ensure_nested_map(data), do: data
end

# Your example data which is needed for compilation
data = %{
  callback_query: nil,
  channel_post: nil,
  chosen_inline_result: nil,
  edited_message: nil,
  inline_query: nil,
  message: %Nadia.Model.Message{
    audio: nil,
    caption: nil,
    channel_chat_created: nil,
    chat: %Nadia.Model.Chat{
      first_name: "Christian",
      id: 543_211_234,
      last_name: "Tovar",
      photo: nil,
      title: nil,
      type: "private",
      username: "ChristianTovar"
    },
    contact: nil,
    date: 1_562_605_521,
    delete_chat_photo: nil,
    document: nil,
    edit_date: nil,
    entities: nil,
    forward_date: nil,
    forward_from: nil,
    forward_from_chat: nil,
    from: %Nadia.Model.User{
      first_name: "Christian",
      id: 543_211_234,
      last_name: "Tovar",
      username: "ChristianTovar"
    },
    group_chat_created: nil,
    left_chat_member: nil,
    location: nil,
    message_id: 714,
    migrate_from_chat_id: nil,
    migrate_to_chat_id: nil,
    new_chat_member: nil,
    new_chat_photo: [],
    new_chat_title: nil,
    photo: [],
    pinned_message: nil,
    reply_to_message: nil,
    sticker: nil,
    supergroup_chat_created: nil,
    text: "google meets",
    venue: nil,
    video: nil,
    voice: nil
  },
  update_id: 412_827_321
}

# Here we are ensuring that both ways gives exactly same results
Example.sample(data) == ExampleDynamic.sample(data)

Please let me know if you have any questions.

Related documentation:

  1. &:maps.map/2
  2. &Enum.map/2
  3. &Map.from_struct/1
  4. Guards
  5. Map (describes specific update syntax)
12
Post #6
tovarchristian21

tovarchristian21 OP

Outstanding! Bravo! Thanks for the help, very complete module indeed.

idi527

idi527

:waving_hand:

Why do you want to convert these structs to maps? Maybe there’s an easier way to accomplish what you want … Personally, I don’t remember having problems with :nadia’s structs.

elielhaouzi

elielhaouzi

  def map_from_struct(%_{__meta__: %{__struct__: _}} = schema) when is_map(schema) do
    schema
    |> Map.from_struct()
    |> from_ecto_struct()
  end

  def map_from_struct(map) when is_map(map) do
    map
    |> Enum.reduce(%{}, fn {key, value}, acc ->
      value =
        case value do
          %_{__meta__: %{__struct__: _}} ->
            from_ecto_struct(value)

          value when is_list(value) ->
            value |> Enum.map(&from_ecto_struct/1)

          _ ->
            value
        end

      Map.put_new(acc, key, value)
    end)
  end

We write a lib of utils around ecto https://github.com/annatel/antl_utils_ecto

one of the functionality is
AntlUtilsEcto.map_from_struct(my_schema)

dodul

dodul

The simplest solution that I found is using Poison.

struct = %{
  callback_query: nil,
  channel_post: nil,
  chosen_inline_result: nil,
  edited_message: nil,
  inline_query: nil,
  message: %Nadia.Model.Message{
    audio: nil,
    caption: nil,
    channel_chat_created: nil,
    chat: %Nadia.Model.Chat{
      first_name: "Christian",
      id: 543211234,
      last_name: "Tovar",
      photo: nil,
      title: nil,
      type: "private",
      username: "ChristianTovar"
    },
    contact: nil,
    date: 1562605521,
    delete_chat_photo: nil,
    document: nil,
    edit_date: nil,
    entities: nil,
    forward_date: nil,
    forward_from: nil,
    forward_from_chat: nil,
    from: %Nadia.Model.User{
      first_name: "Christian",
      id: 543211234,
      last_name: "Tovar",
      username: "ChristianTovar"
    },
    group_chat_created: nil,
    left_chat_member: nil,
    location: nil,
    message_id: 714,
    migrate_from_chat_id: nil,
    migrate_to_chat_id: nil,
    new_chat_member: nil,
    new_chat_photo: [],
    new_chat_title: nil,
    photo: [],
    pinned_message: nil,
    reply_to_message: nil,
    sticker: nil,
    supergroup_chat_created: nil,
    text: "google meets",
    venue: nil,
    video: nil,
    voice: nil
  },
  update_id: 412827321
}

{:ok, json_string} = struct |> Poison.encode
{:ok, map} = json_string |> Poison.decode
map 

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews