将json映射提取到结构中的更好方法

将json映射提取到结构中的更好方法,json,parsing,elixir,Json,Parsing,Elixir,我是elixir的新手,我想解析一个json文件。其中一部分是对象的问答数组。 [ { “问题ID”:1, “问题”:“信息:个人信息:姓名”, 回答:“乔” }, { “问题ID”:3, “问题”:“信息:个人信息:姓氏”, 回答:“史密斯” }, ... ] 我知道我想要什么问题ID,我将为1=名字,2=姓氏制作一张地图 但目前我正在做以下工作,将数据放入结构中 defmodule Student do defstruct first_name: nil, last_name: nil

我是elixir的新手,我想解析一个json文件。其中一部分是对象的问答数组。 [ { “问题ID”:1, “问题”:“信息:个人信息:姓名”, 回答:“乔” }, { “问题ID”:3, “问题”:“信息:个人信息:姓氏”, 回答:“史密斯” }, ... ]

我知道我想要什么问题ID,我将为1=名字,2=姓氏制作一张地图

但目前我正在做以下工作,将数据放入结构中

defmodule Student do

  defstruct first_name: nil, last_name: nil, student_number:  nil

  defguard is_first_name(id) when id == 1

  defguard is_last_name(id) when id == 3

  defguard is_student_number(id) when id == 7

end

defmodule AFMC do

  import Student
  @moduledoc """
  Documentation for AFMC.
  """

  @doc """
  Hello world.

  ## Examples

      iex> AFMC.hello
      :world

  """
  def main do
    get_json()
    |> get_outgoing_applications
  end

  def get_json do
    with {:ok, body} <- File.read("./lib/afmc_import.txt"),
          {:ok,body} <- Poison.Parser.parse(body), do: {:ok,body}
  end

  def get_outgoing_applications(map) do
    {:ok,body} = map
    out_application = get_in(body,["outgoingApplications"])


    Enum.at(out_application,0)
    |> get_in(["answers"])
    |> get_person
  end

  def get_person(answers) do

    student = Enum.reduce(answers,%Student{},fn(answer,acc) ->

      if Student.is_first_name(answer["questionId"]) do

        acc = %{acc | first_name: answer["answer"]}

      end

      if Student.is_last_name(answer["questionId"]) do

        acc = %{acc | last_name: answer["answer"]}

      end

      if Student.is_student_number(answer["questionId"]) do

        acc = %{acc | student_number: answer["answer"]}

      end

      acc

    end)

    IO.inspect "test"
    s



  end


end
defmodule学生做什么
defstruct名字:nil,姓氏:nil,学生编号:nil
当id==1时,defguard是第一个名称(id)
当id==3时,defguard是姓(id)
当id==7时,defguard是学生号(id)
结束
DEFMC模块
进口学生
@moduledoc”“”
AFMC的文件。
"""
@“医生”
你好,世界。
##例子
iex>AFMC.hello
:世界
"""
def主do
get_json()
|>获取\u传出的\u应用程序
结束
def get_json do
与{:好的,身体}得到你的人
结束
def get_person(答案)do
学生=Enum.reduce(答案,%student{},fn(答案,acc)->
如果学生的名字(回答[“问题ID]”)是什么
acc=%{acc |名字:答案[“答案”]}
结束
如果学生的姓(回答[“问题ID]”)是什么
acc=%{acc |姓氏:答案[“答案”]}
结束
如果学生。学生号(回答[“问题ID]”)是多少
acc=%{acc |学生编号:答案[“答案”]}
结束
行政协调会
(完)
IO.检查“测试”
s
结束
结束
我想知道在不必做if语句的情况下,做get_person的更好方法是什么。如果我知道,我将在对象数组中将1映射到questionId 1。 然后,数据将保存到数据库中


谢谢

我将存储id到字段名的映射。这样,在reduce中就不需要任何
if
。一些模式匹配也会使您无需执行
回答[“questionId”]
等操作

defmodule Student do
  defstruct first_name: nil, last_name: nil, student_number: nil

  @fields %{
    1 => :first_name,
    3 => :last_name,
    7 => :student_number
  }

  def parse(answers) do
    Enum.reduce(answers, %Student{}, fn %{"questionId" => id, "answer" => answer}, acc ->
      %{acc | @fields[id] => answer}
    end)
  end
end

IO.inspect(
  Student.parse([
    %{"questionId" => 1, "question" => "", "answer" => "Joe"},
    %{"questionId" => 3, "question" => "", "answer" => "Smith"},
    %{"questionId" => 7, "question" => "", "answer" => "123"}
  ])
)
输出:

%Student{first_name: "Joe", last_name: "Smith", student_number: "123"}
编辑:要跳过地图中不存在的ID,请更改:

%{acc | @fields[id] => answer}
致:


我将存储id到字段名的映射。这样,在reduce中就不需要任何
if
。一些模式匹配也会使您无需执行
回答[“questionId”]
等操作

defmodule Student do
  defstruct first_name: nil, last_name: nil, student_number: nil

  @fields %{
    1 => :first_name,
    3 => :last_name,
    7 => :student_number
  }

  def parse(answers) do
    Enum.reduce(answers, %Student{}, fn %{"questionId" => id, "answer" => answer}, acc ->
      %{acc | @fields[id] => answer}
    end)
  end
end

IO.inspect(
  Student.parse([
    %{"questionId" => 1, "question" => "", "answer" => "Joe"},
    %{"questionId" => 3, "question" => "", "answer" => "Smith"},
    %{"questionId" => 7, "question" => "", "answer" => "123"}
  ])
)
输出:

%Student{first_name: "Joe", last_name: "Smith", student_number: "123"}
编辑:要跳过地图中不存在的ID,请更改:

%{acc | @fields[id] => answer}
致:


我得到一个密钥“零未找到”错误。如果找不到Id,则应跳过它。我假设这就是为什么会出现错误。我已经编辑了答案,以包含对此的修复。让我知道它是否有效!作品谢谢,仍然习惯于模式匹配,我尝试过使用if Map.has_key,但没有成功,但我想那是因为我忘记了else并返回了acc。我得到了一个key nil not found错误。如果找不到Id,则应跳过它。我假设这就是为什么会出现错误。我已经编辑了答案,以包含对此的修复。让我知道它是否有效!作品谢谢,仍然习惯于模式匹配,我尝试过使用if Map.has_key,但没有成功,但我想那是因为我忘记了else并返回了acc。