如何在 Absinthe GraphQL 请求中接受 JSON

Pir*_*nha 5 elixir phoenix-framework absinthe

我试图在我的 graphql 实现中接收一串 JSON,但是我定义的用于处理 JSON 的自定义标量不断出现错误。

我已经定义了一个自定义标量来正确地将 JSON 序列化为 elixir 映射。在我的代码到达自定义标量的解析阶段之前,我收到错误数据类型无效。我正在尝试使用https://github.com/absinthe-graphql/absinthe/wiki/Scalar-Recipes#json-using-jason来创建标量,但是我已经修改为使用 Poison 而不是 Jason。

我的 absinthe mutator 使用我创建的 :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
Run Code Online (Sandbox Code Playgroud)

我的标量定义和 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
Run Code Online (Sandbox Code Playgroud)

发送以下查询时:

    mutation updateUser{
      updateUser(client_store: "{"key":"value"}"){
        id
      }
    }
Run Code Online (Sandbox Code Playgroud)

我收到一个 syntax error before: \"\\\":\\\"\"

    mutation updateUser{
      updateUser(client_store: "hello"){
        id
      }
    }
Run Code Online (Sandbox Code Playgroud)

我收到一个 "Argument \"client_store\" has invalid value \"hello\"

通过单元测试发送 GraphQL 查询 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)
Run Code Online (Sandbox Code Playgroud)

Gab*_*Prá 6

问题在于您的突变,您需要转义字符串中的引号,如下所示:

mutation updateUser{
  updateUser(client_store: "{\"key\": \"value\"}"){
    id
  }
}
Run Code Online (Sandbox Code Playgroud)

否则,解释是第二个引号标记字符串的结尾,因此您基本上在字符串"{"后跟key":"value"}",这在语法上是无效的。

请注意,在单元测试中发送变更时,您已经将变更定义为字符串,因此您需要进一步转义引号:

query = """
    mutation updateUser{
      updateUser(client_store: "{\\\"key\\\":\\\"value\\\"}"){
        id
      }
    }
  """
Run Code Online (Sandbox Code Playgroud)

一开始可能有点难以理解,但打印出来会更清楚:

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
      }
    }
Run Code Online (Sandbox Code Playgroud)

所以最后一个有效,因为当字符串被评估时,结果是原始突变,它转义了引号。