简体   繁体   中英

Scala create multi-line JSON String

I'm trying to create a multi-line String in Scala as below.

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

It's a nested JSON and it's not displaying properly when I print it. The message field inside errorMessage (which is the output of calling getMessage on an instance of a Throwable ) is causing the issue because it looks like there is a newline right before

at [Source: ... .

If I get rid of that line the JSON displays properly. Any ideas on how to properly format this are appreciated.

EDIT: The issue is with the newline character. So I think the question is more concisely - how to handle the newline within the triple quotes so that it's still recognized as a JSON?

EDIT 2: message is being set by a variable like so:

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

where ex is a Throwable . An example of the contents of that getMessage call is provided above.

I assume that your question has nothing to do with JSON, and that you're simply asking how to create very wide strings without violating the horizontal 80-character limit in your Scala code. Fortunately, Scala's string literals have at least the following properties:

  • You can go from ordinary code to string-literal mode using quotes "..." and triple quotes """...""" .
  • You can go from string-literal mode to ordinary code mode using ${...}
  • Free monoid over characters is reified as methods, that is, there is the + operation that concatenates string literals.
  • The whole construction can be made robust to whitespace and indentation using | and stripMargin .

All together, it allows you to write down arbitrary string literals without ever violating horizontal character limits, in a way that is robust wrt indentation.

In this particular case, you want to make a line break in the ambient scala code without introducing a line break in your text. For this, you simply

  • exit the string-literal mode by closing """
  • insert concatenation operator + in code mode
  • make a line-break
  • indent however you want
  • re-enter the string-literal mode again by opening """

That is,

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

will create the string "blah-blah" , without line break in the produced string.


Applied to your concrete problem:

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

Maybe a more readable option would be to construct the lengthy message separately from the neatly indented JSON, and then use string interpolation to combine the two components:

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

If the message itself contains line breaks

Since JSON does not allow multiline string literals, you have to do something else:

  • To remove line breaks, use .replaceAll("\\\\n", "") or rather .replaceAll("\\\\n", " ")
  • To encode line breaks with the escape sequence \\n , use .replaceAll("\\\\n", "\\\\\\\\n") (yes... backslashes...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM