2015-08-31 4 views
1

У меня есть комплекс JSON, который хранится в базе данных. Это сложность "сегрегация" в "блоках", следующим образом:Ошибка Накопление с проверкой Scalaz

Всего JSON:

{ 
    "block1" : { 
     "param1" : "val1", 
     "param2" : "val2" 
    }, 
    "block2" : { 
     "param3" : "val3", 
     "param4" : "val4" 
    }, 
    ... 
} 

В базе данных, каждый блок хранится и обрабатывает индивидуально:

сохранялись Блоки

"block1" : { 
    "param1" : "val1", 
    "param2" : "val2" 
} 

"block2" : { 
    "param3" : "val3", 
    "param4" : "val4" 
} 

Каждый блок имеет деловое значение, поэтому каждый из них является m приложен к классу case. Я создаю API-интерфейс Play, который хранит, обновляет и извлекает эту структуру JSON, и я хочу проверить, изменил ли кто-то свои данные ради целостности.

Я делаю выборку (парсинг и проверку) каждый блок следующим образом:

val block1 = Json.parse(block1).validate[Block1].get 
val block2 = Json.parse(block2).validate[Block2].get 
... 

прецедентного классы:

trait Block 
sealed case class Block1 (param1: String, param2: String, ...) extends Block 
sealed case class Block2 (param3: String, param4: String, ...) extends Block 
sealed case class Request (block1: Block1, block2: Block2, ...) 

с текущей структурой, если какое-то поле изменяется и не соответствует определенному типу для него. Проигрывает это исключение:

[NoSuchElementException: JsError.get]

Итак, я хочу создать накопительную структуру ошибок с помощью Scalaz и Validation, которые поймут все возможные ошибки синтаксического анализа и проверки. Я видел this и this поэтому я закодировал проверку достоверности таким образом:

def build(block1: String, block2: String, ...): Validation[NonEmptyList[String], Request] = { 
    val block1 = Option(Json.parse(block1).validate[Block1].get).toSuccess("Error").toValidationNel 
    val block2 = Option(Json.parse(block2).validate[Block2].get).toSuccess("Error").toValidationNel 
    ... 

    val request = (Request.apply _).curried 

    blockn <*> (... <*> (... <*> (...<*> (block2 <*> (block1 map request))))) 
} 

Обратите внимание, что я использую аппликативный функтор <*>, потому что Request имеет 20 полеев (здание, которое является Скобка-беспорядком с этим синтаксисом) , |@| применимый функтор применяется только для классов классов до 12 параметров.

Этот код работает для счастливого пути, но, когда я изменяю какое-либо поле, Play выдает исключение Execution, описанное ниже.

Вопрос: Я хочу, чтобы аккумулировать все возможные дефекты структуры, которые Play можно обнаружить при анализе каждого блока. Как я могу это сделать?

Примечание: Если каким-то образом Shapeless имеет какое-то отношение к этому, я открыт для его использования (я его уже использую).

ответ

2

Если многократная валидация является единственной причиной добавления Scalaz в ваш проект, то почему бы не рассмотреть альтернативу, которая не потребует, чтобы вы адаптировали свой Play-проект к монадическому способу, в котором Scalaz заставляет вас решать проблемы (что может быть хорошо, но не обязательно, если единственная причина для этого - многовариантность).

Вместо рекомендуется использовать стандартный подход Scala с scala.util.Try:

val block1 = Try(Json.parse(block1).validate[Block1].get) 
val block2 = Try(Json.parse(block2).validate[Block2].get) 
... 

val allBlocks : List[Try[Block]] = List(block1, block2, ...) 
val failures : List[Failure[Block]] = allBlocks.collect { case f : Failure[Block] => f } 

Таким образом, вы можете работать на стандартных коллекций SCALA, чтобы получить список неудач, подлежащих обработке в дальнейшем. Также этот подход не ограничивает вас по количеству блоков.

+0

Почему отрицательный, пожалуйста? Это не ответ на вопрос. Я хочу собрать все возможные структурные ошибки, которые Play может обнаружить при разборе каждого блока. Как я могу это сделать?'? –

+0

Я не тот, кто отклонил ваш ответ. На самом деле, я думаю, что полностью верна ваша мысль об использовании стандартного Try вместо проверки Scalaz, но у меня есть вопрос об этом: почему вы говорите, что «... если единственная причина для этого - многовариантность»? Есть ли «потенциальное злоупотребление» Scalaz, если я использую только проверку? –

+0

Я видел немало проектов, в которых скалаз использовался прежде всего для его возможностей проверки, поэтому, я думаю, его нельзя классифицировать как «неправильное использование». Проблема здесь заключается в крутой кривой обучения и отсутствии хорошей документации. Скалаз огромна и невероятно мощна, и решение встраивать его в систему должно быть сознательным, учитывая будущее обслуживание кода и насколько легко на борту новых разработчиков. Также он способствует определенному стилю кодирования и построения, что не обязательно то, что вы бы сделали в стандартной Scala. Поэтому мой ответ, который дает альтернативу :) –

Смежные вопросы