【问题标题】:Return Granite validation errors as JSON以 JSON 形式返回 Granite 验证错误
【发布时间】:2018-09-11 11:45:47
【问题描述】:

我有一个带有一些验证的 Granite User 模型。当有人向users/new 发出POST 请求时,我想将验证错误(如果有)作为JSON 返回。目前,我有:

if user.errors.size > 0
  halt env, status_code: 500, response: user.errors.to_json
end

但是当我尝试编译时,我得到:

in /usr/local/Cellar/crystal/0.26.1/src/json/to_json.cr:66: no overload 
matches 'Granite::Error#to_json' with type JSON::Builder
Overloads are:
- Object#to_json(io : IO)
- Object#to_json()

  each &.to_json(json)
         ^~~~~~~

【问题讨论】:

    标签: crystal-lang kemal


    【解决方案1】:

    所以问题是User#errors 是一个Array(Granite::Error),即一个Array 持有Granite::Errors。不幸的是,它看起来不像Granite::Error 实现了to_json(JSON::Builder) 方法(即方法to_json 采用JSON::Builder 类型的参数),Array#to_json 依赖于它(您看到的 sn-p 来自Array#to_json的实现,你可以view on GitHub。)。

    我建议使用JSON.build 自己构建 JSON。这具有额外的副作用,即保持您响应的 JSON(我想它正在被某些客户端使用)完全由 您的 控制。如果 Granite 的开发人员要更改他们在 JSON 中编码 Granite::Errors 的方式,而您正在使用他们的 to_json 方法,那么该更改不会在编译时引发任何问题。

    作为旁注,我建议不要使用状态码 500 来表示验证错误,因为这通常是为服务器内部的意外错误保留的。 4xx 错误(例如 400 - Bad Request)会更合适。作为第二个旁注,将POST 设置为/users 端点会更加RESTful,而不是/users/new

    通过这些更改,生成的 sn-p 如下所示:

    if user.errors.size > 0
      errors_as_json = JSON.build do |json|
        json.array do
          user.errors.each do |error|
            json.string error.to_s
          end
        end
      end
      halt env, status_code: 400, response: errors_as_json
    end
    

    【讨论】:

    • 感谢您的帮助!我已经有一段时间没有时间从事那个项目了。一旦我这样做了,如果你的解决方案有效,我会接受它作为答案。
    猜你喜欢
    • 2021-04-08
    • 2020-01-23
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多