如何在 Absinthe GraphQL 请求中接受 JSON
How to accept JSON in Absinthe GraphQL requests
我试图在我的 graphql 实现中接收 JSON 的字符串,但我定义的用于处理 JSON 的自定义标量不断出现错误。
我定义了一个自定义标量以正确地将 JSON 序列化为 elixir 映射。在我的代码到达自定义标量的解析阶段之前,我收到错误消息,指出我的数据类型无效。我正在尝试使用 https://github.com/absinthe-graphql/absinthe/wiki/Scalar-Recipes#json-using-jason 创建标量,但是我已经修改为使用 Poison 而不是 Jason。
我的苦艾酒突变体使用我创建的 :json 标量类型。
@desc "Update user"
field :update_user, type: :user do
arg(:email, :string)
arg(:password, :string)
arg(:first_name, :string)
arg(:last_name, :string)
arg(:age, :integer)
arg(:client_store, :json)
resolve(handle_errors(&Resolvers.User_Resolver.update_user/3))
end
我的标量定义和 graphql 模式定义
scalar :json, name: "Json" do
description("""
The `Json` scalar type represents arbitrary json string data, represented as UTF-8
character sequences. The Json type is most often used to represent a free-form
human-readable json string.
""")
serialize(&encode/1)
parse(&decode/1)
end
# @spec decode(Absinthe.Blueprint.Input.String.t) :: {:ok, :string} | :error
# @spec decode(Absinthe.Blueprint.Input.Null.t) :: {:ok, nil}
defp decode(%Absinthe.Blueprint.Input.String{value: value}) do
Logger.info "decoded input value:"
case Poison.decode(value) do
{:ok, result} -> {:ok, result}
_ -> :error
end
end
defp decode(%Absinthe.Blueprint.Input.Null{}) do
{:ok, nil}
end
defp decode(_) do
:error
end
defp encode(value), do: value
object :user do
field(:id, :id)
field(:email, :string)
field(:password, :string)
field(:first_name, :string)
field(:last_name, :string)
field(:age, :integer)
field(:client_store, :json)
end
发送以下查询时:
mutation updateUser{
updateUser(client_store: "{"key":"value"}"){
id
}
}
我收到一个syntax error before: \"\\":\\"\"
mutation updateUser{
updateUser(client_store: "hello"){
id
}
}
我收到一个"Argument \"client_store\" has invalid value \"hello\"
通过 Phoenix.ConnTest
通过单元测试发送 GraphQL 查询
query = """
mutation updateUser{
updateUser(client_store: "{\"key\":\"value\"}"){
id
}
}
"""
res =
context.conn
|> put_req_header("content-type", "text")
|> put_req_header("authorization", token)
|> post("/api", query)
问题出在你的突变上,你需要转义字符串中的引号,如下所示:
mutation updateUser{
updateUser(client_store: "{\"key\": \"value\"}"){
id
}
}
否则,解释是第二个引号标记字符串的结尾,所以基本上字符串 "{"
后跟 key":"value"}"
,这在语法上是无效的。
请注意,在单元测试中发送突变时,您已经将突变定义为字符串,因此您需要进一步转义引号:
query = """
mutation updateUser{
updateUser(client_store: "{\\"key\\":\\"value\\"}"){
id
}
}
"""
一开始理解起来可能有点棘手,但打印出来会更清楚:
iex(1)> """
...(1)> mutation updateUser{
...(1)> updateUser(client_store: "{\"key\":\"value\"}"){
...(1)> id
...(1)> }
...(1)> }
...(1)> """ |> IO.puts()
mutation updateUser{
updateUser(client_store: "{"key":"value"}"){
id
}
}
iex(2)> """
...(2)> mutation updateUser{
...(2)> updateUser(client_store: "{\\"key\\":\\"value\\"}"){
...(2)> id
...(2)> }
...(2)> }
...(2)> """ |> IO.puts()
mutation updateUser{
updateUser(client_store: "{\"key\":\"value\"}"){
id
}
}
所以最后一个有效,因为当对字符串求值时,结果是原始变异,它避开了引号。
我正在这样测试
test "should get an existing key" do
{:ok, user} = Api.Auth.Users.create_user(%{name: "Test User"})
{:ok, app} = Api.Auth.Apps.create_app(%{owner_id: %{type: :user, id: user.id}, name: "name"})
{:ok, key} = Api.Auth.Keys.create_key(%{app_id: app.id})
%{resp_body: response} =
build_conn()
|> post("graphql", %{
"query" => """
query {
key(id: "#{key.id}") {
id
}
}
"""
})
%{"data" => %{"key" => %{"id" => id}}} = Jason.decode!(response)
assert key.id == id
end
end
我试图在我的 graphql 实现中接收 JSON 的字符串,但我定义的用于处理 JSON 的自定义标量不断出现错误。
我定义了一个自定义标量以正确地将 JSON 序列化为 elixir 映射。在我的代码到达自定义标量的解析阶段之前,我收到错误消息,指出我的数据类型无效。我正在尝试使用 https://github.com/absinthe-graphql/absinthe/wiki/Scalar-Recipes#json-using-jason 创建标量,但是我已经修改为使用 Poison 而不是 Jason。
我的苦艾酒突变体使用我创建的 :json 标量类型。
@desc "Update user"
field :update_user, type: :user do
arg(:email, :string)
arg(:password, :string)
arg(:first_name, :string)
arg(:last_name, :string)
arg(:age, :integer)
arg(:client_store, :json)
resolve(handle_errors(&Resolvers.User_Resolver.update_user/3))
end
我的标量定义和 graphql 模式定义
scalar :json, name: "Json" do
description("""
The `Json` scalar type represents arbitrary json string data, represented as UTF-8
character sequences. The Json type is most often used to represent a free-form
human-readable json string.
""")
serialize(&encode/1)
parse(&decode/1)
end
# @spec decode(Absinthe.Blueprint.Input.String.t) :: {:ok, :string} | :error
# @spec decode(Absinthe.Blueprint.Input.Null.t) :: {:ok, nil}
defp decode(%Absinthe.Blueprint.Input.String{value: value}) do
Logger.info "decoded input value:"
case Poison.decode(value) do
{:ok, result} -> {:ok, result}
_ -> :error
end
end
defp decode(%Absinthe.Blueprint.Input.Null{}) do
{:ok, nil}
end
defp decode(_) do
:error
end
defp encode(value), do: value
object :user do
field(:id, :id)
field(:email, :string)
field(:password, :string)
field(:first_name, :string)
field(:last_name, :string)
field(:age, :integer)
field(:client_store, :json)
end
发送以下查询时:
mutation updateUser{
updateUser(client_store: "{"key":"value"}"){
id
}
}
我收到一个syntax error before: \"\\":\\"\"
mutation updateUser{
updateUser(client_store: "hello"){
id
}
}
我收到一个"Argument \"client_store\" has invalid value \"hello\"
通过 Phoenix.ConnTest
query = """
mutation updateUser{
updateUser(client_store: "{\"key\":\"value\"}"){
id
}
}
"""
res =
context.conn
|> put_req_header("content-type", "text")
|> put_req_header("authorization", token)
|> post("/api", query)
问题出在你的突变上,你需要转义字符串中的引号,如下所示:
mutation updateUser{
updateUser(client_store: "{\"key\": \"value\"}"){
id
}
}
否则,解释是第二个引号标记字符串的结尾,所以基本上字符串 "{"
后跟 key":"value"}"
,这在语法上是无效的。
请注意,在单元测试中发送突变时,您已经将突变定义为字符串,因此您需要进一步转义引号:
query = """
mutation updateUser{
updateUser(client_store: "{\\"key\\":\\"value\\"}"){
id
}
}
"""
一开始理解起来可能有点棘手,但打印出来会更清楚:
iex(1)> """
...(1)> mutation updateUser{
...(1)> updateUser(client_store: "{\"key\":\"value\"}"){
...(1)> id
...(1)> }
...(1)> }
...(1)> """ |> IO.puts()
mutation updateUser{
updateUser(client_store: "{"key":"value"}"){
id
}
}
iex(2)> """
...(2)> mutation updateUser{
...(2)> updateUser(client_store: "{\\"key\\":\\"value\\"}"){
...(2)> id
...(2)> }
...(2)> }
...(2)> """ |> IO.puts()
mutation updateUser{
updateUser(client_store: "{\"key\":\"value\"}"){
id
}
}
所以最后一个有效,因为当对字符串求值时,结果是原始变异,它避开了引号。
我正在这样测试
test "should get an existing key" do
{:ok, user} = Api.Auth.Users.create_user(%{name: "Test User"})
{:ok, app} = Api.Auth.Apps.create_app(%{owner_id: %{type: :user, id: user.id}, name: "name"})
{:ok, key} = Api.Auth.Keys.create_key(%{app_id: app.id})
%{resp_body: response} =
build_conn()
|> post("graphql", %{
"query" => """
query {
key(id: "#{key.id}") {
id
}
}
"""
})
%{"data" => %{"key" => %{"id" => id}}} = Jason.decode!(response)
assert key.id == id
end
end