2017-02-01 8 views
1

を構造体へのマップを変換します私は次のように構造体へのマップを変換しようとしています

私は、地図を持っている:

iex(6)> user      
%{"basic_auth" => "Basic Ym1hOmphYnJhMTc=", "firstname" => "foo", 
    "lastname" => "boo"} 

値は構造体に適用する必要があります。

iex(7)> a = struct(UserInfo, user) 
%SapOdataService.Auth.UserInfo{basic_auth: nil, firstname: nil, lastname: nil} 

として、 structの値がnilであるのはなぜですか?

+0

http://stackoverflow.com/questions/30927635/in-elixir-how-do-you-initialize-a-struct-with-a-map-variable – sobolevn

+0

@sobolevnこれはまさにOPが試みたものです。 JustMichaelが示唆したように、マップに文字列キーがあるため、マップは機能しません。 –

答えて

2

JustMichaelの答えに展開するには、あなたが最初にString.to_existing_atom/1を使用して、原子にキーを変換することができ、Kernel.struct/2:ドキュメントへ

defmodule TestStruct do 
    defstruct field_one: nil, 
      field_two: nil, 
      field_three: nil, 
      field_four: nil 
    use ExConstructor 
end 

TestStruct.new(%{"field_one" => "a", "fieldTwo" => "b", :field_three => "c", :FieldFour => "d"}) 
# => %TestStruct{field_one: "a", field_two: "b", field_three: "c", field_four: "d"} 

はリンク:ここで小さな例です

:これはVMあちこちを防ぐためにString.to_existing_atom/1を使用していることを

user_with_atom_keys = for {key, val} <- user, into: %{} do 
    {String.to_existing_atom(key), val} 
end 

user_struct = struct(UserInfo, user_with_atom_keys) 
# %UserInfo{basic_auth: "Basic Ym1hOmphYnJhMTc=", firstname: "foo", 
lastname: "boo"} 

注意グローバルなAtom制限に達する。

2

マップに文字列として、構造体にアトムとしてキーがあるため、私の野生の推測ではうまくいかないでしょう。

1

私はこのためにエクトのチェンジセットを使用したい:

defmodule UserInfo do 
    use Ecto.Schema 

    schema "user_info" do 
    field :basic_auth, :string 
    field :firstname, :string 
    field :lastname, :string 
    end 
end 

その後、どこかにあなたのコード内

import Ecto.Changeset 

user_struct = cast(%UserInfo{}, 
        your_user_map, 
        UserInfo.__schema__(:fields)) 
       |> apply_changes 

エクトのこの使用のいいところは、あなたが、検証のような利点が追加されていることで、あなたのマップのフィールドが文字列か原子かを心配する必要はありません。

+0

超クールなソリューション – simo

関連する問題