Scala 创建多行 JSON 字符串

Scala create multi-line JSON String

我正尝试在 Scala 中创建一个多行字符串,如下所示。

val errorReport: String =
    """
      |{
      |"errorName":"blah",
      |"moreError":"blah2",
      |"errorMessage":{
      |         "status": "bad",
      |         "message": "Unrecognized token 'noformatting': was expecting 'null', 'true', 'false' or NaN
 at [Source: (ByteArrayInputStream); line: 1, column: 25]"
      | }
      |}
      """
   .stripMargin

它是嵌套的 JSON,打印时显示不正确。 errorMessage 中的 message 字段(这是在 Throwable 的实例上调用 getMessage 的输出)导致了这个问题,因为看起来前面有一个换行符

at [Source: ...

如果我删除该行,JSON 会正确显示。任何关于如何正确格式化的想法都将受到赞赏。

编辑:问题出在换行符上。所以我认为问题更简洁 - 如何处理三重引号内的换行符,以便它仍然被识别为 JSON?

编辑 2:message 由这样的变量设置:

"message": "${ex.getMessage}"

其中 exThrowable。上面提供了该 getMessage 调用的内容示例。

我假设您的问题与 JSON 无关,并且您只是在询问如何创建非常宽的字符串而不违反 Scala 代码中的水平 80 个字符限制。幸运的是,Scala 的字符串文字至少具有以下属性:

  • 您可以使用引号 "..." 和三引号 """...""".
  • 从普通代码转到字符串文字模式
  • 您可以使用 ${...}
  • 从字符串文字模式转到普通代码模式
  • 字符上的自由幺半群被具体化为方法,即有 + 连接字符串文字的操作。
  • 可以使用 |stripMargin.
  • 使整个结构对空格和缩进具有鲁棒性

总之,它允许您以稳健的方式写下任意字符串文字,而不会违反水平字符限制 w.r.t。缩进。

在这种特殊情况下,您希望在环境 Scala 代码中进行换行而不在文本中引入换行。为此,您只需

  • 通过关闭 """
  • 退出字符串文字模式
  • 在代码模式下插入连接运算符+
  • 换行
  • 随心所欲地缩进
  • 再次打开"""
  • 重新进入字符串文字模式

"""blah-""" +
"""blah"""

将创建字符串 "blah-blah",生成的字符串中没有换行符。


应用于您的具体问题:

val errorReport: String = (
    """{
      |  "errorName": "blah",
      |  "moreError": "blah2",
      |  "errorMessage": {
      |    "status": "bad",
      |    "message": "Unrecognized token 'noformatting'""" +
    """: was expecting 'null', 'true', 'false' or NaN at """ +
    """[Source: (ByteArrayInputStream); line: 1, column: 25]"
      |  }
      |}
      """
  ).stripMargin

也许一个更具可读性的选择是将冗长的消息与整齐缩进的 JSON 分开构建,然后使用字符串插值来组合这两个部分:

val errorReport: String = {
  val msg = 
    """Unrecognized token 'noformatting': """ +
    """was expecting 'null', 'true', 'false' or NaN at """ +
    """[Source: (ByteArrayInputStream); line: 1, column: 25]"""

    s"""{
      |  "errorName": "blah",
      |  "moreError": "blah2",
      |  "errorMessage": {
      |    "status": "bad",
      |    "message": "${msg}"
      |  }
      |}
      """
  }.stripMargin

如果消息本身包含换行符

由于JSON不允许多行字符串文字,你必须做一些别的事情:

  • 要删除换行符,请使用 .replaceAll("\n", "").replaceAll("\n", " ")
  • 要使用转义序列 \n 对换行符进行编码,请使用 .replaceAll("\n", "\\n")(是的...反斜杠...)