Вернуть ошибки проверки гранита в формате JSON

У меня есть гранит User модель с некоторыми проверками. Когда кто-то делает POST запросить users/newЯ хотел бы вернуть ошибки проверки (если таковые имеются) в виде 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)
         ^~~~~~~

1 ответ

Решение

Так что проблема в том, что User#errors является Array(Granite::Error) т.е. Array держа Granite::Error s. К сожалению, это не похоже на Granite::Error реализует to_json(JSON::Builder) метод (то есть метод to_json принимая параметр типа JSON::Builder), который Array#to_json опирается на (этот фрагмент, который вы видите, есть от реализации Array#to_json который вы можете посмотреть на GitHub.).

Я бы порекомендовал создать JSON самостоятельно, используя JSON.build, Это имеет дополнительный побочный эффект, заключающийся в том, что JSON, с которым вы отвечаете (который, как мне кажется, используется некоторым клиентом), полностью находится под вашим контролем. Если бы разработчики Granite должны были изменить способ кодирования Granite::Error с в JSON, и вы использовали их to_json метод, изменение не вызовет ничего во время компиляции.

Как примечание, я бы рекомендовал не использовать код состояния 500 для обозначения ошибки проверки, так как обычно она зарезервирована для непредвиденных ошибок внутри вашего сервера. Ошибка 4xx (например, 400 - неверный запрос) была бы более подходящей. В качестве второго примечания было бы более полезно POST быть сделано в /users конечная точка, в отличие от /users/new,

С этими изменениями здесь будет получен фрагмент:

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
Другие вопросы по тегам