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