json - 将json映射提取到结构中的更好方法
问题描述
我是 elixir 的新手,我想解析一个 json 文件。其中一个部分是对象的问答数组。[ { "questionId":1, "question":"信息:个人信息:名字", "answer":"Joe" }, { "questionId":3, "question":"信息:个人信息:姓氏", "答案":"史密斯" }, ... ]
我知道我想要什么 questionId,我将为 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
我想知道什么是更好的方法来做 get_person 而不必做 if 语句。如果我知道我将在对象数组中将 1 映射到 questionId 1。然后将数据保存到数据库中。
谢谢
解决方案
我会存储 id 到字段名称的映射。这样你就不需要if
在reduce里面有任何东西了。一些模式匹配也会使得它没有必要做answer["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}
到:
if field = @fields[id], do: %{acc | field => answer}, else: acc
推荐阅读
- mysql - 我应该如何修改我的触发器,以便我可以根据他们的部门获得 total_employees?
- python - Python html-requests render() 不呈现 javascript 元素
- java - 拆分后打印字符串的一部分
- c - 布尔数据类型随机整数
- mongodb - $reduce 和 $setUnion 用于 MongoDB 中的嵌套数组
- javascript - 在 Meteor 中找不到 Gijgo 字体图标
- javascript - 当 json 具有相同名称的键时,new Map() 如何在 javascript 中工作
- angular - 将数据添加到新文本框的问题
- kubernetes - 在排空之前将单独的 pod 移动到不同节点的推荐方法是什么?这样 kubectl drain node1 --force 不会删除 pod
- css - 转发时内容相互中断