如何编写惯用Scala包装类来表示非惯用JSON

如何编写惯用Scala包装类来表示非惯用JSON,json,scala,playframework-2.2,Json,Scala,Playframework 2.2,我正在编写一些Scala类来模拟JSON API的结果(这不在我的控制之下) 我使用的是Play2,最简单的方法似乎是使用case类,使参数的名称与JSON中的键的名称匹配。但是有一个问题,JSON对象在TitleCase中有键,而在Scala中,好的样式要求参数和属性在camelCase中(而TitleCase是保留给类的,就像在Java中一样) 我曾经考虑过创建一个Reads对象,将TitleCase键映射到case类构造函数中参数的顺序,但是保持同步看起来很麻烦,我基本上需要将所有定义编写

我正在编写一些Scala类来模拟JSON API的结果(这不在我的控制之下)

我使用的是Play2,最简单的方法似乎是使用case类,使参数的名称与JSON中的键的名称匹配。但是有一个问题,JSON对象在TitleCase中有键,而在Scala中,好的样式要求参数和属性在camelCase中(而TitleCase是保留给类的,就像在Java中一样)

我曾经考虑过创建一个
Reads
对象,将TitleCase键映射到case类构造函数中参数的顺序,但是保持同步看起来很麻烦,我基本上需要将所有定义编写两次。因此,这大部分被丢弃

另一个选项是对JSON进行预处理,将所有键转换为camelCase,然后将其提供给默认的
Reads
。但我还不知道如何在游戏中做到这一点(我想它应该只是一个递归函数,接受一个
JSObject
,然后生成另一个,但这可能不是很有效,因为它需要重新创建整个JSON映射……也许有一种有效的方法可以使用Jackson的流式API来实现)

最后,最后一个选择是接受它,让关键字出现在TitleCase中,即使这只适用于类和单例对象


我敢打赌,这个问题经常出现(如果不是用带下划线的TitleCase而不是带空格的TitleCase),在Scala和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类

自定义读取组合器的优点之一是,您能够利用一些自定义验证器,例如电子邮件,它将“必须传递电子邮件正则表达式”要求应用于我的电子邮件,作为对象验证过程的一部分

只要JSON的所有必填字段大小写正确(该部分必须保持同步),该读取将验证JSON。其余部分完全可延展;它对顺序不敏感


不幸的是,它没有解决您的问题,保持两个定义同步;一些工具可能会有所帮助,但它无法解决核心问题。

是的,这就是我所说的定制读取,在播放2.1之前我不知道该如何操作。。。最后,我实现了JSON预处理以使字段符合camelCase,它只需要5行代码(Scala的惊人之处);但我又遇到了另一个挫折:API响应有33个字段,案例类最多只支持22个字段:-/我想我可以用一个普通类来解决这个问题;值得注意的是,在Scala 2.11中,case类将能够接受22个以上的参数,在接下来的几周内,Scala 2.11将转向RC1太好了!由于这是一个不太紧急的辅助项目,我想我会等到RC1出来:D