如何覆盖JS对象上的toString()方法以使用JSON.stringify()?

时间:2016-11-02 01:58:33

标签: scala.js

当我处理我的DTO对象时,我已经厌倦了写blah: "${JSON.stringify(target)}",我只想写blah: "$target"

我的DTO看起来像:

@js.native
trait AuthConnectionDetails extends js.Object {
  def clientId: String = js.native
  def accountHostname: String = js.native
}

这些DTO用于解析某些REST API调用的内容,例如:

val response = js.JSON.parse(xmlHttpRequest.responseText).
  asInstanceOf[AuthConnectionDetails]

我不介意改变我如何定义我的DTO对象来执行此操作(也许我应该使用案例类来处理我的DTO或其他东西,而不是本机js特征?),但我无法弄清楚如何做它

我尝试写一个我可以混合的特性,但这不起作用,我尝试编写一个隐式扩展方法,但这也不起作用。

我的隐式代码似乎不适用于toString:

object JsonToString {
  implicit class JsObjectExtensions(val target: js.Object) extends AnyVal {
    override def toString:String = JSON.stringify(target)
    def json:String = JSON.stringify(target)
  }
}

所以我可以做blah: "${target.json}",这更好 - 但我特别想摆脱那些括号。

有没有办法用scala.js做这个?

2 个答案:

答案 0 :(得分:3)

如果你真的想,你可以写自定义字符串插补器:

implicit class JsonHelper(private val sc: StringContext) extends AnyVal {
  def dejson(args: Any*): JSONObject = {
    sc.checkLengths(args)
    s(args.map(jsonify))
  }

  private def jsonify(arg: Any) = arg match {
    case obj: js.Object => JSON.stringify(obj)
    case _ => arg.toString
  }
}

您现在可以像这样使用:

dejson"hello: $target, world: $target2"

答案 1 :(得分:2)

不,没有办法做到这一点。这是因为字符串插值总是使用对象本身的toString()方法 ,无论在其类型或隐式类中声明 这是一般的Scala事。)

实现这一目标的唯一方法是,每次创建对象时,通过使用自定义toString()方法修补对象来实际修改对象。这将包括从JSON字符串解析它们时。我非常确定,当你对它们进行字符串化时,会比调用.json更糟糕。