Dear reader of Juri's TechBlog,
I moved my blog to a new domain and a new hosting solution as well. I'm now blogging on juristr.com.

"\n" will break your JSON jQuery - WCF service call

I recently coded a WCF REST webservice that needed to be accessed from JavaScript. Basically it was a system to provide admins of websites with a real-time system for managing info messages, intended to be displayed beneath input fields. jQuery came in quite handy in this context (as you may imagine ;) ). I used the standard $.ajax(...) function for sending/retrieving JSON encoded data to my webservice and everything wrapped up and displayed nicely within a small model popup window. That worked out quite well until some more intensive tests I made during which I discovered problems in case of multi-line text messages, i.e. within a text area. During transmission the following exception got fired:

{"ExceptionDetail":
 {"HelpLink":null,
  "InnerException":
  {"HelpLink":null,
   "InnerException":
   {"HelpLink":null,
    "InnerException":null,
    "Message":"Encountered invalid character '\u000a'.",
    "StackTrace":"   in System.Runtime.Serialization.Json.XmlJsonReader.ComputeQuotedTextLengthUntilEndQuote(Byte[] buffer, Int32 offset, Int32 offsetMax, Boolean& escaped)
         in System.Runtime.Serialization.Json.XmlJsonReader.ReadQuotedText(Boolean moveToText)
         in System.Runtime.Serialization.Json.XmlJsonReader.Read()
         in System.Xml.XmlBaseReader.ReadElementContentAsString()
         in System.Runtime.Serialization.XmlReaderDelegator.ReadElementContentAsString()
         in System.Runtime.Serialization.Json.JsonStringDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
         in System.Runtime.Serialization.Json.JsonDataContract.ReadJsonValue(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
         in System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
         in System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName)",
     "Type":"System.FormatException"},
 ...

The most interesting part is the one I highlighted. The problem was clear, the newline character broke my JSON string which could then no more be deserialized on the server-side. As you can see from the transmitted data
{"keycode": "ContractFilter_txtCNCN_Desc", "messageDe": "ddd

d", "messageIt": "d"}
it got split up into multiple lines, breaking the JSON format basically.

The solution is at hand: these newline chars have to be encoded. One approach could be to make use of the JavaScript escape(..) function, but this has the drawback of polluting your transmitted string with these strange encoding chars and you would have somehow the need to again unescape it on the server side for having your data stored cleanly. Therefore a better, and probably more simple solution is to have a function like this:
/*
*  Escape newline chars for being transmitted with JSON over the wire
*/
function escapeNewLineChars(valueToEscape) {
    if (valueToEscape != null && valueToEscape != "") {
        return valueToEscape.replace(/\n/g, "\\n");
    } else {
        return valueToEscape;
    }
}
The comment pretty much explains what it does. It basically replaces all occurrences of "\n" (newline chars) with "\\n", basically escaping them. The transmitted JSON string
{"keycode": "ContractFilter_txtCNCN_PROT_NR", "messageDe": "ddd\n\nd", "messageIt": "d"}
looks clean and moreover it can be stored on the server-side without any further interventions. Other functions which you might find quite handy...
/*
*  Converts \n newline chars into <br> chars s.t. they are visible
*  inside HTML
*/
function convertToHTMLVisibleNewline(value) {
    if (value != null && value != "") {
        return value.replace(/\n/g, "<br/>");
    } else {
        return value;
    }
}

/*
*  Converts <br> chars into \n newline chars s.t. they are visible
*  inside text edit boxes
*/
function convertToTextVisibleNewLine(value) {
    if (value != null && value != "") {
        return value.replace(/\<br\>/g, "\n");
    } else {
        return value;
    }
}

Posts you might also be interested in..

Credits: Hoctro | Jack Book

2 Comments:

Anonymous said...

Thank you!

Anonymous said...

nice post...
so much help!

Post a Comment