我正在编写一些Scala类来模拟JSON API的结果(不受我的控制)。
我正在使用Play 2,最直接的方法似乎是使用case类并使参数的名称与JSON中的键的名称相匹配。但是有一个问题,JSON对象在 TitleCase中有键,而在Scala中,良好的样式表明参数和属性在 camelCase (和 TitleCase 中>保留给类,如Java)。
我考虑创建一个Reads
对象,将 TitleCase 键映射到案例类构造函数中的参数顺序,但这看起来很麻烦,以保持同步我需要基本上写两次所有定义。所以这大部分都被丢弃了。
另一种选择可能是预处理JSON以将所有密钥转换为 camelCase ,然后将其提供给默认的Reads
。但我还不知道如何在Play中执行此操作(我猜它应该只是一个递归函数,需要JSObject
,并产生另一个,但这可能不是很有效,因为它需要重新创建整个JSON映射......也许有一种使用Jackson的流API实现这一点的有效方法。)
最后,最后一个选项是使用它并让关键字出现在 TitleCase 中,即使这只是针对类和单例对象的。
我敢打赌,这个问题非常复发(如果没有 TitleCase with underscore_instead_of_spaces),在Scala和Play框架中处理这种情况的惯用方法是什么?
答案 0 :(得分:4)
你的帖子提到你想过根据参数的映射顺序构建一个Reads;那当然很麻烦。您是否考虑使用Play中引入的JSON组合器创建自定义读取! 2.1?那里的负担有点低;它的顺序不敏感
### Case Class
case class User(id: Option[Long] = None, username: String, firstName: String,
lastName: String, email: String, password: String)
### Reads
implicit val userReads: Reads[User] = (
(__ \ 'username).read[String] and
(__ \ 'firstname).read[String] and
(__ \ 'lastname).read[String] and
(__ \ 'email).read[String](email) and
(__ \ 'password).read[String]
) {
(username: String, firstName: String, lastName: String, email: String,
password: String) =>
User(None, username, firstName, lastName, email, password)
}
你可以在这里看到我将一个完全小写的json对象映射到一个带有camelcase的case类
自定义读取组合器的优点之一就是您可以利用一些自定义验证器,例如电子邮件,它将“必须通过电子邮件正则表达式”要求应用于我的电子邮件是对象验证过程的一部分。
此Reads将验证JSON,只要它具有正确大写的所有必需字段(该部分必须保持同步)。其余部分是完全可塑的;它的顺序不敏感。
不幸的是,它没有解决您将两个定义保持同步的问题;一些工具可能是一个帮助,但它不会解决核心问题。