I can't get replaceAll to work on the '\r\n' sequence in a JSON serialized string.

I am serializing a Map object that contains long textarea fields with newlines. I need to change '\r\n' to '\\r\\n' for Javascript purposes. When I serialize the object, I see '\r\n' in the resulting string. However, none of the replaceAll lines that I try will work:

Map<Id, Job_Posting__c> jobMap = new Map<Id, Job_Posting__c>();
// job map gets populated.
String x = JSON.serialize(jobMap);
String y = x.replaceAll('\r\n', '\\r\\n');
String z = x.replaceAll('\\r\\n', '\\\\r\\\\n');

Is there something about JSON serialized strings that force a different approach? I see that the serialized string is between double quotes - does that make a difference?

Details: I want to pass a serialized map of job posting records to a Javascript function in a Visualforce page. The Javascript JSON.parse() fails with "unexpected token" when it hits the '\r\n'. If I manually edit the JSON string to be '\\r\\n' then the parse works.

Here's the Javascript on the VF page:

    // Define the CCx.pageJobSelection module - can be moved to static resource
    (function (module, $) {
        "use strict";
        var data_jobPostings;

        // intercept the 'submit' action of the HTML form 
        jQuery(document).ready( function ($) {
            //processing here.

        module.initialize = function (options) {
            data_jobPostings = JSON.parse(options.jobPostings);

    })(CCx.pageJobSelection = CCx.pageJobSelection || {}, jQuery);

    // initialize the module
        jobPostings: '{!jobMapJSON}'


Here's the VF controller:

public with sharing class HL_CCx_JobSelectionController {
    public String jobMapJSON { get; private set; }
    public List<Job_Posting__c> jobs { get; private set; }
    private Map<Id, Job_Posting__c> jobMap = new Map<Id, Job_Posting__c>();

    // Constructor
    public HL_CCx_JobSelectionController() {
        jobs = CCx_JobSelector.selectActiveJobs();
        if (jobs == null) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'No jobs postings available.'));


        // Serialize
        jobMapJSON = JSON.serialize(jobMap);
        jobMapJSON = jobMapJSON.replaceAll('\r\n', '\\r\\n');
  • Can you explain a bit more why you want to do this replacement? JSON supports \r\n and most JSON is valid JavaScript too. – Keith C Jun 16 '14 at 16:49
  • @KeithC - I added some explanation to the original post, thanks. – David Cheng Jun 16 '14 at 17:04
  • Once you have an apex string, it shouldn't matter where the string came from. What happens if you do this: (a) get the serialized JSON string from this controller, copy to clipboard, (b) run in anonymous window: String j = 'STRING FROM FIRST STEP'; System.debug(j.replaceAll('\r\n', '\\r\\n'); – Benj Jun 16 '14 at 17:27
  • Alternatively, what if you make the replacement in javascript? data_jobPostings = JSON.parse( options.jobPostings.replace(/\r\n/g, '\\r\\n') ); – Benj Jun 16 '14 at 17:30
  • When I do that in Apex I get 'rn', when I do the replace in Javascript I don't get any errors, but there's no line break between the text lines. – David Cheng Jun 16 '14 at 18:21

Why not just emit the JSON into the page so it is immediately parsed by JavaScript:


and then there is no need to parse yourself:

module.initialize = function (options) {
    data_jobPostings = options;

This should avoid the need for any replacing.

Its also worth using JSON.serializePretty to make the JSON easier to manually review when you do a "View Page Source" of the page.


This page:

<apex:page controller="AbcController">
var map = {!jsonString};

and controller (where cve__OccupationalDescription__c is a custom text area field):

public class AbcController {
    public String jsonString {
        get {
            return JSON.serializePretty(new Map<Id, Contact>([
                    select Id, FirstName, LastName, cve__OccupationalDescription__c
                    from Contact
                    limit 2

produce this valid JSON that the browser's JavaScript engine is happy with:

var map = {
  "003A000000ou3XLIAY" : {
    "attributes" : {
      "type" : "Contact",
      "url" : "/services/data/v30.0/sobjects/Contact/003A000000ou3XLIAY"
    "cve__OccupationalDescription__c" : "Line 1.\r\nLine 2.\r\nLine 3.",
    "RecordTypeId" : "012A0000000zC62IAE",
    "FirstName" : "Tim",
    "Id" : "003A000000ou3XLIAY",
    "LastName" : "Jones"
  "003A000000pm2plIAA" : {
    "attributes" : {
      "type" : "Contact",
      "url" : "/services/data/v30.0/sobjects/Contact/003A000000pm2plIAA"
    "RecordTypeId" : "012A0000000zC62IAE",
    "FirstName" : "Derek",
    "Id" : "003A000000pm2plIAA",
    "LastName" : "O'Brien"
| improve this answer | |
  • if the OP wants to pass in an options object (rather than a single data value), it could also work like this: CCx.pageJobSelection.initialize( options = data_jobPostings: {!jobMapJSON} ); – Benj Jun 16 '14 at 17:58
  • If I try just {!jobMapJSON} or options = data_jobPostings: {!jobMapJSON}, I get unexpected token errors. – David Cheng Jun 16 '14 at 18:19
  • @DavidCheng Perhaps you can post what "View Page Source" shows you and the specific error message? I just added a working example to the answer. – Keith C Jun 16 '14 at 18:51
  • Thanks, I went back to your original code snippets and it worked. I had extra curly braces in the initialize method that caused the unexpected token error. – David Cheng Jun 16 '14 at 20:04
  • That's a nice workaround but I wish there was an answer to the question of why \r\n can't be replaced in JSON – Amalgovinus Jan 26 '19 at 0:10
final String CRLF = '\r\n';

String x = '\r\n';
String expected = '\\r\\n';

System.assertEquals(expected, x.replaceAll(CRLF, '\\\\r\\\\n'));
| improve this answer | |
  • Alan - if you serialize x, then it doesn't work. – David Cheng Jun 16 '14 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.