Scala создать многострочную строку JSON - PullRequest
2 голосов
/ 01 апреля 2019

Я пытаюсь создать многострочную строку в 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, и он не отображается должным образом, когда я его печатаю. Поле message внутри errorMessage (которое является выходом вызова getMessage для экземпляра Throwable) вызывает проблему, поскольку похоже, что перед

есть новая строка

at [Source: ....

Если я избавлюсь от этой строки, JSON отобразится правильно. Любые идеи о том, как правильно отформатировать это приветствуется.

РЕДАКТИРОВАТЬ: Проблема с символом новой строки. Поэтому я думаю, что вопрос более лаконичен - как обработать символ новой строки в тройных кавычках, чтобы он все еще распознавался как JSON?

РЕДАКТИРОВАТЬ 2: message устанавливается переменной, например:

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

, где ex - это Throwable. Пример содержимого этого вызова getMessage приведен выше.

1 Ответ

2 голосов
/ 01 апреля 2019

Я предполагаю, что ваш вопрос не имеет ничего общего с JSON, и вы просто спрашиваете, как создать очень широкие строки без нарушения горизонтального 80-символьного ограничения в вашем коде Scala. К счастью, строковые литералы Scala имеют как минимум следующие свойства:

  • Вы можете перейти от обычного кода к строковому буквальному режиму, используя кавычки "..." и тройные кавычки """...""".
  • Вы можете перейти из строкового литерального режима в обычный кодовый режим, используя ${...}
  • Свободный моноид над символами определяется как методы, то есть есть операция +, которая объединяет строковые литералы.
  • Вся конструкция может быть сделана устойчивой к пробелам и отступам, используя | и stripMargin.

Все вместе, это позволяет вам записывать произвольные строковые литералы, никогда не нарушая горизонтальные ограничения символов, таким способом, который является надежным w.r.t. отступы.

В этом конкретном случае вы хотите сделать разрыв строки в окружающем скала-коде, не вводя разрыв строки в вашем тексте. Для этого вы просто

  • выйти из строкового литерального режима, закрыв """
  • вставить оператор конкатенации + в режиме кода
  • сделать разрыв строки
  • отступ, как вы хотите
  • снова войти в режим строкового литерала, открыв """

То есть

"""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", " ")
  • Чтобы кодировать разрывы строк с помощью escape-последовательности \n, используйте .replaceAll("\\n", "\\\\n") (да ... обратные косые черты ...)
...