0

I have a json in which I store a property with a link. I want to write this to a .txt file so I can copy the content and use it in a resource object which has a serverUrl variable that I want to inject using template literals. Before I can do that I need to change the string value of the JSON a bit so I can use the template literals.

The json object has the following format:

{
  "products": [
    {
      "image": "http://test.test.com/images/imageName.jpg"
    },
    {
      "image": "http://test.test.com/images/imageName2.jpg"
    }
  ]
}

What I am trying to achieve is to change every image value to the following format for each product object:

`http://${serverUrl}/images/imagename`

I managed to replace the url using a simple string.replace() during the json creation, but I am struggling with the following steps:

  1. Change the double quotes to graves ("" => ``) and keep the url.
  2. Do it globaly, I don't want to extract the values, the object should be overwritten.

I've tried writing some regexes, but I can't seem to figure out how I can replace both the double quotes and keep the url in one regex. Is this the right way to go about this? Or should I try something completely different

Edit

My code so far

let dataImport = [];

// Code to convert excel to JSON
// Contains the following line for the image property
case "image": 
  value = value.replace("https://test.test.com", "${serverUrl}");
  rowData["image"] = value;
break;

// Convert object
let json = JSON.stringify(dataImport, null, 2);
fs.writeFileSync("data.txt", json);
Jordi
  • 3,041
  • 5
  • 17
  • 36
  • Using backticks in JSON would make the JSON invalid. – Andy Oct 15 '19 at 13:56
  • 1
    Do you have *JSON* or an *object*? JSON is a text format for serialising *objects* that *looks similar to* object literals in JavaScript, however backticks are not valid syntax within it. Objects are plain JS literals that do allow any JS syntax, including backticks. With that said, template literals are evaluated *when encountered*, you cannot "store" something like `\`Hello ${name}\`` and later perform the evaluation. You can put that in a function that accepts `name`, for example and thus evaluates the expression when called. – VLAZ Oct 15 '19 at 13:57
  • I'm trying to do this replace on a string value after calling JSON.stringify() on my object. Would this bypass the issue? I'm not trying to actually use the JSON, I just want to write the replaced result to a .txt file. – Jordi Oct 15 '19 at 14:01
  • *"I'm not trying to actually use the JSON, I just want to write the replaced result to a .txt file."* I assume you will read the data at some point somehow. How do you plan to do that? – Felix Kling Oct 15 '19 at 14:17
  • You can change what you get after you've done `JSON.stringify` and then write the data to a file. However afterwards you'd need a custom parser when you read your file, since you'd no longer have JSON. You'd have something that approximates JSON but will cause all JSON parsers to error when reading it. You're better off using basic string substitution on serialising/deseralising, if you really want that. So you'd transform any URL to something like `"http://${serverUrl}/images/imagename"` (or whatever custom template marker you choose) and replace it back on read. – VLAZ Oct 15 '19 at 14:29
  • Sorry, but in my attempt to make everything more understandable, I left out an important detail. I wont be reading the .txt file. I will copy it's content to an static object which uses the template literal. This approach already works, so I'm really only looking for a solution to the replacement of the double quotes – Jordi Oct 15 '19 at 14:36
  • So you are saying that you are embedding the contents of the text file into JavaScript code verbatim? I.e. the content will be evaluated as JavaScript? – Felix Kling Oct 16 '19 at 12:04
  • Yes the content has been added as an array with objects – Jordi Oct 16 '19 at 14:29

1 Answers1

1

var json = JSON.stringify({
  "products": [
    {
      "image": "http://test.test.com/images/imageName.jpg"
    },
    {
      "image": "http://test.test.com/images/imageName2.jpg"
    }
  ]
}, null, '  ');

var domain = "test.test.com";
console.log(convertJsonUrls(json, domain));

/**
 * Converts any strings containing urls for the specified domain into template-strings,
 * and replaces the domain with '${serverUrl}'
 */
function convertJsonUrls(json, domain) {
    var stringRE = /"((?:\\.|[^\\"])*)"/g;
    var urlRE = new RegExp("^(https?://)" + escapeRegExp(domain) + "(/.*)$");

    var template = json.replace(stringRE, function (raw, content) {
        var urlMatch = urlRE.exec(content);
        if (!urlMatch) return raw; // no change, keep double-quotes
        return "`" + urlMatch[1] + "${serverUrl}" + urlMatch[2] + "`";
    });

    return template;
}

/**
 * Escapes any RegExp special characters.
 * Copied from https://stackoverflow.com/a/6969486/22364
 */
function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138