2013-09-22 3 views
2

Я хочу реализовать BodyParser, который анализирует и проверяетrequest.body, он основан на parse.json и в настоящее время выглядит следующим образом:BodyParser вернуть результат на основании запроса органа

def parseModel[A](implicit reads: Reads[A]): BodyParser[JsResult[A]] = 
    parse.json.map(_.validate[A]) 

Проблема в том, это в настоящее время типа BodyParser[JsResult[A]], пока я хочу, чтобы он был типа BodyParser[A]. В случае JsError я хочу, чтобы он в основном возвращал 400 Bad Request с ошибками проверки.

В Play API docs Я не могу найти метод, который позволяет мне проверять результат предыдущего анализатора тела и возвращать результат или перейти к контроллеру.

ответ

10

A BodyParser, после разбора тела, производит Either[SimpleResult, A], где SimpleResult - это результат ошибки, который должен быть немедленно возвращен вместо обработки. Методы удобства на BodyParser не позволяют сделать это, поэтому вместо того, чтобы создать новый анализатор тела, что делегаты тела парсер JSON:

def validateJson[A](implicit reads: Reads[A]) = new BodyParser[A] { 
    def apply(request: RequestHeader) = parse.json(request).map(_.right.flatMap { json => 
    json.validate[A].asEither.left.map(e => BadRequest(JsError.toFlatJson(e))) 
    }) 
} 

Здесь можно увидеть, что мы отображающая результат синтаксического анализа , а затем значение right (успешный синтаксический разбор, будет JsValue) и вызывает на нем flatMap. Наш метод flatMap преобразует JsResult от validate к Either[JsError, A], так что мы уже на полпути там с A, после того, что мы map слева JsError в SimpleResult, и мы хорошо идти.

0

Хорошо, я реализовал желаемое поведение с помощью метода, который производит Action:

def validateJson[A](implicit reads: Reads[A]) = 
    parse.json.map(_.validate[A]) 


def ModelAction[A](action: A => Result)(implicit r: Reads[A]) = 
    Action(validateJson[A]) { request => 
    request.body match { 
     case JsSuccess(model, _) => action(model) 
     case JsError(e) => BadRequest(JsError.toFlatJson(e)) 
    } 
    } 

я могу использовать его как это:

def create = ModelAction[MyModel] { model => 
    ??? 
} 

Я все еще интересно, если это возможно сделать то же самое с BodyParser, и если мне нужно это сделать или это лучше, как сейчас?

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