Closed RecursionTaoist closed 1 month ago
My attempt ...
2
prompts the Runtime.argParse to deserialize the request bodycode:
/**
* Builds a implicit request body json parser.
*
* @tparam T the type of deserialize.
* @return request body json parser.
* @note This parser read bytes from request body directly.
* @note Do not support custom [[FieldSerializer]] (field rename to / from
* and ignore).
* @note Setting the arity value to `2` prompts the
* [[formula.router.Runtime.argParse]] to serialize the request body.
*/
implicit def defaultJsonParser[T <: Product : Manifest]: BasicParser[T] =
new BasicParser[T] {
/**
* Indicates the json request body, need to deserialize.
*/
override def arity: Int = 2
/**
* @inheritdoc
*/
override def parse(
req: Request,
name: String,
input: Seq[String]
): T = {
implicit val formats: Formats = DefaultFormats
read[T](req.data.text)
}
}
/**
* Parses the argument of the given `signature` to the target type by i
* input value, additional parameters or raw [[Request]] (decided by th
* `arity`) via the corresponding `parse` function.
*
* @param args arguments map for obtaining the input value.
* @param req [[Request]].
* @param default function to build default value.
* @param signature argument signature.
* @tparam IN the type of input.
* @return parse result in [[Any]] if successfully, a sequence of
* [[Result.ParamError]] otherwise.
* @note Invoked by macro-generated code, used for [[Entry]] building.
*/
def argParse[IN](
args: Map[String, IN],
req: Request,
default: => Option[Any],
signature: ArgSig[IN, _, _]
): Either[Seq[Result.ParamError], Any] = {
signature.parser.arity match {
case 0 =>
// query parameters
tryEither(
signature.parser.parse(
req,
signature.name,
null.asInstanceOf[IN]
),
Result.ParamError.DefaultFailed(signature, _)
).left.map(Seq(_))
case 1 =>
// normal argument list or its default value if input is absent
args.get(signature.name) match {
case None =>
tryEither(
default.get,
Result.ParamError.DefaultFailed(signature, _)
).left.map(Seq(_))
case Some(x) =>
tryEither(
signature.parser.parse(
req,
signature.name,
x
),
Result.ParamError.Invalid(signature, x.toString, _)
).left.map(Seq(_))
}
case 2 =>
// only for json parse from request body, see BasicParser
tryEither(
signature.parser.parse(
req,
signature.name,
null.asInstanceOf[IN]
),
Result.ParamError.DefaultFailed(signature, _)
).left.map(Seq(_))
}
}
results show:
package example
import scala.util.{Failure, Success, Try}
/**
* Example application.
*/
object HelloWorld extends formula.MainRoutes {
/**
* Json post demo, mixed use of path variable, query parameters and json
* request body.
*
* @param skill path variable.
* @param score path variable.
* @param params query parameters.
* @param profile request body.
* @return response.
*/
@formula.json.post("/refine/:skill/with/:score")
def refine(
skill: String,
score: Float,
params: formula.Params,
profile: Profile
): Profile = {
val expertise = params.map({
case (k, vs) =>
Try(vs.head.toFloat) match {
case Success(s) => k -> s
case Failure(_) => k -> 0.0f
}
})
Profile(
name = profile.name,
age = profile.age,
level = profile.level,
expertise = profile.expertise + (skill -> score) ++ expertise
)
}
initialize()
}
/**
* For test.
*/
case class Profile(
name: String,
age: Int,
level: String,
expertise: Map[String, Float]
)
like @RequestBody annotation to read the request body and deserialized into an Object in springbot