Are there any classes/functions available to be used for easy JSON escaping? I'd rather not have to write my own.
I use System.Web.HttpUtility.JavaScriptStringEncode
string quoted = HttpUtility.JavaScriptStringEncode(input);
For those using the very popular Json.Net project from Newtonsoft the task is trivial:
using Newtonsoft.Json;
....
var s = JsonConvert.ToString(#"a\b");
Console.WriteLine(s);
....
This code prints:
"a\\b"
That is, the resulting string value contains the quotes as well as the escaped backslash.
Building on the answer by Dejan, what you can do is import System.Web.Helpers .NET Framework assembly, then use the following function:
static string EscapeForJson(string s) {
string quoted = System.Web.Helpers.Json.Encode(s);
return quoted.Substring(1, quoted.Length - 2);
}
The Substring call is required, since Encode automatically surrounds strings with double quotes.
Yep, just add the following function to your Utils class or something:
public static string cleanForJSON(string s)
{
if (s == null || s.Length == 0) {
return "";
}
char c = '\0';
int i;
int len = s.Length;
StringBuilder sb = new StringBuilder(len + 4);
String t;
for (i = 0; i < len; i += 1) {
c = s[i];
switch (c) {
case '\\':
case '"':
sb.Append('\\');
sb.Append(c);
break;
case '/':
sb.Append('\\');
sb.Append(c);
break;
case '\b':
sb.Append("\\b");
break;
case '\t':
sb.Append("\\t");
break;
case '\n':
sb.Append("\\n");
break;
case '\f':
sb.Append("\\f");
break;
case '\r':
sb.Append("\\r");
break;
default:
if (c < ' ') {
t = "000" + String.Format("X", c);
sb.Append("\\u" + t.Substring(t.Length - 4));
} else {
sb.Append(c);
}
break;
}
}
return sb.ToString();
}
I have used following code to escape the string value for json.
You need to add your '"' to the output of the following code:
public static string EscapeStringValue(string value)
{
const char BACK_SLASH = '\\';
const char SLASH = '/';
const char DBL_QUOTE = '"';
var output = new StringBuilder(value.Length);
foreach (char c in value)
{
switch (c)
{
case SLASH:
output.AppendFormat("{0}{1}", BACK_SLASH, SLASH);
break;
case BACK_SLASH:
output.AppendFormat("{0}{0}", BACK_SLASH);
break;
case DBL_QUOTE:
output.AppendFormat("{0}{1}",BACK_SLASH,DBL_QUOTE);
break;
default:
output.Append(c);
break;
}
}
return output.ToString();
}
In .Net Core 3+ and .Net 5+:
string escapedJsonString = JsonEncodedText.Encode(jsonString);
The methods offered here are faulty.
Why venture that far when you could just use System.Web.HttpUtility.JavaScriptEncode ?
If you're on a lower framework, you can just copy paste it from mono
Courtesy of the mono-project #
https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpUtility.cs
public static string JavaScriptStringEncode(string value, bool addDoubleQuotes)
{
if (string.IsNullOrEmpty(value))
return addDoubleQuotes ? "\"\"" : string.Empty;
int len = value.Length;
bool needEncode = false;
char c;
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92)
{
needEncode = true;
break;
}
}
if (!needEncode)
return addDoubleQuotes ? "\"" + value + "\"" : value;
var sb = new System.Text.StringBuilder();
if (addDoubleQuotes)
sb.Append('"');
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62)
sb.AppendFormat("\\u{0:x4}", (int)c);
else switch ((int)c)
{
case 8:
sb.Append("\\b");
break;
case 9:
sb.Append("\\t");
break;
case 10:
sb.Append("\\n");
break;
case 12:
sb.Append("\\f");
break;
case 13:
sb.Append("\\r");
break;
case 34:
sb.Append("\\\"");
break;
case 92:
sb.Append("\\\\");
break;
default:
sb.Append(c);
break;
}
}
if (addDoubleQuotes)
sb.Append('"');
return sb.ToString();
}
This can be compacted into
// https://github.com/mono/mono/blob/master/mcs/class/System.Json/System.Json/JsonValue.cs
public class SimpleJSON
{
private static bool NeedEscape(string src, int i)
{
char c = src[i];
return c < 32 || c == '"' || c == '\\'
// Broken lead surrogate
|| (c >= '\uD800' && c <= '\uDBFF' &&
(i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF'))
// Broken tail surrogate
|| (c >= '\uDC00' && c <= '\uDFFF' &&
(i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF'))
// To produce valid JavaScript
|| c == '\u2028' || c == '\u2029'
// Escape "</" for <script> tags
|| (c == '/' && i > 0 && src[i - 1] == '<');
}
public static string EscapeString(string src)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int start = 0;
for (int i = 0; i < src.Length; i++)
if (NeedEscape(src, i))
{
sb.Append(src, start, i - start);
switch (src[i])
{
case '\b': sb.Append("\\b"); break;
case '\f': sb.Append("\\f"); break;
case '\n': sb.Append("\\n"); break;
case '\r': sb.Append("\\r"); break;
case '\t': sb.Append("\\t"); break;
case '\"': sb.Append("\\\""); break;
case '\\': sb.Append("\\\\"); break;
case '/': sb.Append("\\/"); break;
default:
sb.Append("\\u");
sb.Append(((int)src[i]).ToString("x04"));
break;
}
start = i + 1;
}
sb.Append(src, start, src.Length - start);
return sb.ToString();
}
}
I ran speed tests on some of these answers for a long string and a short string. Clive Paterson's code won by a good bit, presumably because the others are taking into account serialization options. Here are my results:
Apple Banana
System.Web.HttpUtility.JavaScriptStringEncode: 140ms
System.Web.Helpers.Json.Encode: 326ms
Newtonsoft.Json.JsonConvert.ToString: 230ms
Clive Paterson: 108ms
\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\"things\to\escape\some\long\path\with\lots"\of\things\to\escape
System.Web.HttpUtility.JavaScriptStringEncode: 2849ms
System.Web.Helpers.Json.Encode: 3300ms
Newtonsoft.Json.JsonConvert.ToString: 2827ms
Clive Paterson: 1173ms
And here is the test code:
public static void Main(string[] args)
{
var testStr1 = "Apple Banana";
var testStr2 = #"\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\""things\to\escape\some\long\path\with\lots""\of\things\to\escape";
foreach (var testStr in new[] { testStr1, testStr2 })
{
var results = new Dictionary<string,List<long>>();
for (var n = 0; n < 10; n++)
{
var count = 1000 * 1000;
var sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.HttpUtility.JavaScriptStringEncode(testStr);
}
var t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.HttpUtility.JavaScriptStringEncode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.Helpers.Json.Encode(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.Helpers.Json.Encode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = Newtonsoft.Json.JsonConvert.ToString(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Newtonsoft.Json.JsonConvert.ToString").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = cleanForJSON(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Clive Paterson").Add(t);
}
Console.WriteLine(testStr);
foreach (var result in results)
{
Console.WriteLine(result.Key + ": " + Math.Round(result.Value.Skip(1).Average()) + "ms");
}
Console.WriteLine();
}
Console.ReadLine();
}
I would also recommend using the JSON.NET library mentioned, but if you have to escape unicode characters (e.g. \uXXXX format) in the resulting JSON string, you may have to do it yourself. Take a look at Converting Unicode strings to escaped ascii string for an example.
I nice one-liner, used JsonConvert as others have but added substring to remove the added quotes and backslash.
var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
What about System.Web.Helpers.Json.Encode(...) (see http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode(v=vs.111).aspx)?
String.Format("X", c);
That just outputs: X
Try this instead:
string t = ((int)c).ToString("X");
sb.Append("\\u" + t.PadLeft(4, '0'));
There's a Json library at Codeplex
I chose to use System.Web.Script.Serialization.JavaScriptSerializer.
I have a small static helper class defined as follows:
internal static partial class Serialization
{
static JavaScriptSerializer serializer;
static Serialization()
{
serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
}
public static string ToJSON<T>(T obj)
{
return serializer.Serialize(obj);
}
public static T FromJSON<T>(string data)
{
if (Common.IsEmpty(data))
return default(T);
else
return serializer.Deserialize<T>(data);
}
}
To serialize anything I just call Serialization.ToJSON(itemToSerialize)
To deserialize I just call Serialization.FromJSON<T>(jsonValueOfTypeT)
Related
Well this questions is probably gonna be closed before I get an answer... I am trying to program a very simple calculator and this works flawlessly:
private void button1_Click(object sender, EventArgs e)
{
string[] input = rtbInput.Text.Split(' ');
rtbInput.Text += " = " + CalculateNumber(input).ToString();
}
long CalculateNumber(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
//LOOK FOR PARENTHASIS, LAST INDEX, SEARCH FROM THERE UNTIL FIRST INDEX, RUN THIS AGAIN FOR THAT.
//THEN REPLACE "5 + (3 + 3)" with 5 + 6. So calculate 3 + 3 = 6 and replace ( until ) with answer.
if (rtbInput.Text.Contains("(") && rtbInput.Text.Contains(")"))
{
int c = 0;
int startNum;
int len;
string s = "No";
}
int i = 0;
while (i < (input.Length - 1))
{
switch (input[i])
{
case "+":
curValue += long.Parse(input[i + 1]);
break;
case "-":
curValue -= long.Parse(input[i + 1]);
break;
case "*":
curValue = curValue * long.Parse(input[i + 1]);
break;
case "/":
curValue = curValue / long.Parse(input[i + 1]);
break;
}
i++;
}
return curValue;
}
this works superbly. But when trying to add capability to calculate Parenthasis "(3 * 3) = 9" and i implement this code:
long CalculateNumber(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
//LOOK FOR PARENTHASIS, LAST INDEX, SEARCH FROM THERE UNTIL FIRST INDEX, RUN THIS AGAIN FOR THAT.
//THEN REPLACE "5 + (3 + 3)" with 5 + 6. So calculate 3 + 3 = 6 and replace ( until ) with answer.
if (rtbInput.Text.Contains("(") && rtbInput.Text.Contains(")"))
{
int c = 0;
int startNum;
int len;
string s = "No";
//while there are still parenthasis in the input, do this
if (c < rtbInput.Text.Split('(').Count() - 1) //REPLACE WITH WHILE
{
startNum = rtbInput.Text.LastIndexOf('(') + 1;
len = rtbInput.Text.IndexOf(')', startNum);// - startNum;
s = rtbInput.Text.Substring(startNum, len);
this.Name = s;
//NOW REPLACE THIS WITH THE RETURN OF CalculateParenthasis.Split(' ')
rtbInput.Text = rtbInput.Text.Replace("(" + s + ")", CalculateParenthasis(s.Split(' ')).ToString());
}
long CalculateParenthasis(string[] input)
{
long curValue = 0;
curValue = long.Parse(input[0]);
button1.Text += curValue.ToString();
int i = 0;
while (i < (input.Length - 1))
{
switch (input[i])
{
case "+":
curValue += long.Parse(input[i + 1]);
break;
case "-":
curValue -= long.Parse(input[i + 1]);
break;
case "*":
curValue = curValue * long.Parse(input[i + 1]);
break;
case "/":
curValue = curValue / long.Parse(input[i + 1]);
break;
}
i++;
}
return curValue;
}
As you can see the CalculateParenthasis() function works exactly the same as CalculateNumber() but takes the number between the parenthasis, but this errors at the switch statement saying the input string was the wrong format? WTH? I barely don't know how to even ask this question, seems like something tiny and easy being wrong but I just can't see it.
Based on my test, I reproduced the problem you meet.
However, I find it is very hard for us to complete it because of its complexity.
Therefore, I recommend that you use Reverse Poland algorithm to make the calculator.
I make a code example to make it and you can refer to it.
Code:
public class Example
{
public static Stack<string> operStack = new Stack<string>();
public static Stack<string> numStack = new Stack<string>();
static bool IsNumber(string s)
{
return Regex.IsMatch(s, #"\d+");
}
static bool IsSiZe(string s)
{
string ts = "+-*/";
return ts.IndexOf(s) > -1;
}
static int Level(string s)
{
int i = 0;
switch (s)
{
case ",":
i = 0;
break;
case "(":
case ")":
case "#":
i = 1;
break;
case "+":
case "-":
i = 2;
break;
case "*":
case "/":
i = 3;
break;
}
return i;
}
public static void Calc(Stack<string> numStack, Stack<string> operStack)
{
int rightnum = int.Parse(numStack.Pop());
int leftnum = int.Parse(numStack.Pop());
string oper = operStack.Pop();
switch (oper)
{
case "+":
numStack.Push((leftnum + rightnum).ToString());
break;
case "-":
numStack.Push((leftnum - rightnum).ToString());
break;
case "*":
numStack.Push((leftnum * rightnum).ToString());
break;
case "/":
numStack.Push((leftnum / rightnum).ToString());
break;
}
}
public static void ToNiBoLan(string exp)
{
operStack.Push("#"); //Push into the stack for comparsion
string token = "";
for (int i = 0; i < exp.Length; i++)
{
if (IsNumber(exp[i].ToString())) //If it is number
{
token += exp[i].ToString();
}
else if (exp[i].ToString() == "(")
{
operStack.Push(exp[i].ToString());
if (IsNumber(token))
numStack.Push(token);
token = "";
}
else if (IsSiZe(exp[i].ToString()))
{
if (IsNumber(token))
numStack.Push(token);
token = "";
int item = Level(exp[i].ToString()).CompareTo(Level(operStack.Peek())); //Comparison operator precedence
if (item > 0) //If the priority is higher than the top of the stack, the operator is pushed onto the stack
{
operStack.Push(exp[i].ToString());
}
else //If the operator is less than or equal to the top of the stack, calculate and push the operator onto the stack
{
Calc(numStack, operStack);
operStack.Push(exp[i].ToString());
}
}
else if (exp[i].ToString() == ")")
{
if (IsNumber(token))
numStack.Push(token);
token = "";
while (operStack.Peek() != "(")
{
Calc(numStack, operStack);
}
token = numStack.Pop(); //Take out the numbers for the next calculation
operStack.Pop(); //Eligible left parenthesis popped
}
else //End of traversal
{
if (IsNumber(token))
numStack.Push(token);
token = "";
while (numStack.Count > 1)
{
Calc(numStack, operStack);
}
}
}
}
}
Use it in winforms:
private void button1_Click(object sender, EventArgs e)
{
//For comparison, add "#" at the end of the expression
string text = richTextBox1.Text.Trim() + "#";
Example.ToNiBoLan(text);
richTextBox1.Text = Example.numStack.Pop().ToString();
}
Besides, you can refer to the link Reverse polish notation C# don't work correctly.
I want to calculate the summary of string in terms of number of alphabets, digits and special character in C#. For example:
String abc123$% should have summary like A3D3S2 (which means 3 Alphabet, 3 Digits and 2 Special character)
a34=$# should have summary like A1D2S3 (which means 1 Alphabet, 2 Digits and 3 Special character)
a3b$s should have summary like A1D1A1S1A1 (which means 1 Alphabet, 1 Digits,1 Alphabet, 1 Special character,1 Alphabet)
Can anyone guide me how can write an algorithm which can perform the above task in a quick way? as I think if I search the string character by character, then it will take considerable amount of time. and I have a large dataset of strings.
This works:
static string GetSummary(string input)
{
var sb = new StringBuilder();
string prevMode = "";
string curMode = "";
int sameModeCount = 0;
for (int i = 0; i <= input.Length; ++i)
{
if (i < input.Length)
{
char c = input[i];
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')
{
curMode = "A";
}
else if ('0' <= c && c <= '9')
{
curMode = "D";
}
else
{
curMode = "S";
}
}
else
{
curMode = "";
}
if (curMode != prevMode && prevMode != "")
{
sb.Append(prevMode);
sb.Append(sameModeCount);
sameModeCount = 0;
}
prevMode = curMode;
++sameModeCount;
}
return sb.ToString();
}
Test:
public static void Main()
{
Console.WriteLine(GetSummary("abc123$%"));
Console.WriteLine(GetSummary("a34=$#"));
Console.WriteLine(GetSummary("a3b$s"));
}
Results:
A3D3S2
A1D2S3
A1D1A1S1A1
With Linq, you can do like this :
string myinput = "abc123$%";
int letter =0 , digit = 0, specialCharacter = 0;
myinput.ToCharArray().ToList().ForEach(x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ?
++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit,
specialCharacter);
You can directly use array in Linq ForEach without converting to list by :
Array.ForEach(myinput.ToCharArray(), x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ? ++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit, specialCharacter);
This should work:
string s = "a3b$s";
char etype = 'X'; //current character's type
char etypeinit = 'X'; //tracker variable - holds type of last character
string str = "";
int count = 1;
foreach(char c in s)
{
//Use this block of conditionals to assign type for current character
if(char.IsLetter(c))
{
etype = 'A';
}
else if(char.IsDigit(c))
{
etype = 'D';
}
else
{
etype = 'S';
}
//This is a different type of character compared to the previous one
if(etypeinit != etype)
{
str += string.Format("{0}{1}",etype,count); //Build the string
count = 1; //Reset count
}
else
{
count++; //Increment because this is the same type as previous one
}
etypeinit = etype; //Set tracker variable to type of current character
}
Console.WriteLine(str);
Little late and little complex but able to produces all expected output as per given inputs in the question, please take a look:
string inputString = "abc123$%ab12";
var results = inputString.Select(x => char.IsLetter(x) ? 'A' :
char.IsDigit(x) ? 'D' : 'S');
StringBuilder outPutBuilder = new StringBuilder();
char previousChar = results.First();
int charCount = 0;
foreach (var item in results)
{
switch (item)
{
case 'A':
if (previousChar == 'A')
{
charCount++;
}
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
case 'D':
if (previousChar == 'D')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
default:
if (previousChar == 'S')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
}
previousChar = item;
}
outPutBuilder.Append(previousChar.ToString() + charCount);
Working example
Use a FOR loop to go through each character. If the character is in the range of a-z or A-Z then it is an alphabet. If in the range of 0-9 then it is a digit else special character.
Code
string inputStr = "a3b$s";
string outputStr = string.Empty;
char firstChar = Convert.ToChar(inputStr.Substring(0, 1));
outputStr = char.IsLetter(firstChar) ? "A1" : char.IsDigit(firstChar) ? "D1" : "S1";
for (int i = 1; i < inputStr.Length; i++)
{
char nextChar = char.IsLetter(inputStr[i]) ? 'A' :
char.IsDigit(inputStr[i]) ? 'D' : 'S';
char prevChar = Convert.ToChar(outputStr.Substring(outputStr.Length - 2, 1));
if (nextChar == prevChar)
{
int lastDig = Convert.ToInt32(outputStr.Substring(outputStr.Length - 1, 1));
outputStr = outputStr.Substring(0, outputStr.Length - 1) +
(lastDig + 1).ToString();
}
else
outputStr += nextChar.ToString() + "1";
}
Console.WriteLine(outputStr.ToString());
Output
A1D1A1S1A1
Find demo here
I want to convert this () into this ) (
Like for example (1+2) to ) 1+2(
i have tried this
char[] cArray = text.ToCharArray();
for (int i = 0; i < text.Length; i++)
{
if (cArray[i] == '(')
{
cArray[i] = ')';
}
if (cArray[i] == ')')
{
cArray[i] = '(';
}
}
string p=new string(cArray);
return p;
but it does not work
The problem is that after you've changed ( to ), the second if statement will immediately be true, so the character is flipped back again. The reverse isn't true though - if you start off with ) that will be flipped by the second statement, but then it won't be flipped back again. The net result is that all ) characters will be flipped to (, but that's all. So an input of "(((foo)))" would return "(((foo(((.
The simplest way to fix that is to use an else statement:
char[] cArray = text.ToCharArray();
for (int i = 0; i < text.Length; i++)
{
if (cArray[i] == '(')
{
cArray[i] = ')';
}
else if (cArray[i] == ')')
{
cArray[i] = '(';
}
}
return new string(cArray);
Alternatively, you could use a switch statement, which would be simpler if you had a lot of different cases to consider:
char[] cArray = text.ToCharArray();
for (int i = 0; i < text.Length; i++)
{
switch (cArray[i])
{
case '(':
cArray[i] = ')';
break;
case ')':
cArray[i] = '(';
break;
// No need for a default as it would be a no-op
}
}
return new string(cArray);
A switch statement will only evaluate the expression once (on each iteration, of course) so you don't need to worry about the two cases interfering with each other.
Use else before the second if as follows:
char[] cArray = text.ToCharArray();
for (int i = 0; i < text.Length; i++)
{
if (cArray[i] == '(')
{
cArray[i] = ')';
}
else if (cArray[i] == ')')
{
cArray[i] = '(';
}
}
string p = new string(cArray);
return p;
I'm looking for a way to have one string formatting pattern representation for use in both Java and C#.
Java: http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html
C#: http://msdn.microsoft.com/en-us/library/fht0f5be.aspx
The following Java class implements the most important features of the String.Format
method in C#. It supports the 'X' and 'D' format specifiers, but not 'F', 'G', or 'R'.
package com.upokecenter.util;
import java.util.Locale;
public final class DotNetFormatter {
private DotNetFormatter() {
}
public static String format(String formattedText,
Object... options) {
return format(Locale.getDefault(),formattedText,options);
}
public static String format(Locale locale, String formattedText,
Object... options) {
int numOptions = options.length;
StringBuilder buffer = new StringBuilder();
int i;
for (i = 0; i < formattedText.length(); i++) {
char c = formattedText.charAt(i);
if (c == '{') {
i++;
if (i < formattedText.length()) {
c = formattedText.charAt(i);
if (c == '{') {
buffer.append('{');
} else if (c >= '0' || c <= '9') {
int x = (c - '0');
i++;
while (i < formattedText.length()) {
c = formattedText.charAt(i);
if (c == ':') {
i++;
if (x >= numOptions
|| i >= formattedText.length())
throw new IllegalArgumentException(
"Format string contains a badly numbered argument.");
char formatType = formattedText.charAt(i);
if (formatType == 'x' || formatType == 'X'
|| formatType == 'd'
|| formatType == 'D') {
i++;
if (i >= formattedText.length())
throw new IllegalArgumentException(
"Format string contains a badly numbered argument.");
char formatCount = formattedText.charAt(i);
if (formatCount == '}') {
switch (formatType) {
case 'x':
buffer.append(String.format(locale,
"%x", options[x]));
break;
case 'X':
buffer.append(String.format(locale,
"%X", options[x]));
break;
case 'd':
buffer.append(String.format(locale,
"%d", options[x]));
break;
case 'D':
buffer.append(String.format(locale,
"%d", options[x]));
break;
}
break;
} else if (formatCount < '0'
|| formatCount > '9'
|| (++i) >= formattedText.length())
throw new IllegalArgumentException(
"Format string contains a badly numbered argument.");
else {
if (formattedText.charAt(i) != '}')
throw new IllegalArgumentException(
"Format string contains a badly numbered argument.");
String fmt = "";
switch (formatType) {
case 'x':
fmt = String.format("%%0%cx",
formatCount);
break;
case 'X':
fmt = String.format("%%0%cX",
formatCount);
break;
case 'd':
fmt = String.format("%%0%cd",
formatCount);
break;
case 'D':
fmt = String.format("%%0%cd",
formatCount);
break;
}
buffer.append(String.format(locale,
fmt, options[x]));
break;
}
} else {
throw new IllegalArgumentException(
"Format string contains a badly formatted argument.");
}
} else if (c == '}') {
if (x >= numOptions)
throw new IllegalArgumentException(
"Format string contains a badly numbered argument.");
buffer.append(String.format(locale, "%s",
options[x]));
break;
} else if (c >= '0' || c <= '9') {
i++;
x = x * 10 + (c - '0');
} else {
throw new IllegalArgumentException(
"Format string contains a badly formatted argument.");
}
}
} else {
buffer.append('{');
buffer.append(c);
}
} else {
buffer.append(c);
}
} else {
buffer.append(c);
}
}
return buffer.toString();
}
}
I need for someone to be able to put some text into a page and then this gets sent to the server, saved in the database, and else where this text is put into a javascript variable.
Basically like this:
Write("var myVar=\""+MyData+"\";");
What is the best way of escaping this data? Is there anything out there already to deal with things like ' and " and new lines? Is base64 my only option?
My serverside framework/language is ASP.Net/C#
You should use WPL:
Write("var myVar=" + Encoder.JavaScriptEncode(MyData, true) + ";");
if you don't want to reference the library, you can use the following function (adapted from the .Net source):
public static void QuoteString(this string value, StringBuilder b) {
if (String.IsNullOrEmpty(value))
return "";
var b = new StringBuilder();
int startIndex = 0;
int count = 0;
for (int i = 0; i < value.Length; i++) {
char c = value[i];
// Append the unhandled characters (that do not require special treament)
// to the string builder when special characters are detected.
if (c == '\r' || c == '\t' || c == '\"' || c == '\'' || c == '<' || c == '>' ||
c == '\\' || c == '\n' || c == '\b' || c == '\f' || c < ' ') {
if (b == null) {
b = new StringBuilder(value.Length + 5);
}
if (count > 0) {
b.Append(value, startIndex, count);
}
startIndex = i + 1;
count = 0;
}
switch (c) {
case '\r':
b.Append("\\r");
break;
case '\t':
b.Append("\\t");
break;
case '\"':
b.Append("\\\"");
break;
case '\\':
b.Append("\\\\");
break;
case '\n':
b.Append("\\n");
break;
case '\b':
b.Append("\\b");
break;
case '\f':
b.Append("\\f");
break;
case '\'':
case '>':
case '<':
AppendCharAsUnicode(b, c);
break;
default:
if (c < ' ') {
AppendCharAsUnicode(b, c);
} else {
count++;
}
break;
}
}
if (b == null) {
b.Append(value);
}
if (count > 0) {
b.Append(value, startIndex, count);
}
return b.ToString();
}