I am currently serializing an object like this below.
"record" is a string array which has special character in it, like >,<,& etc
The first index in record is "<" and this is a xml special character and which is converted to "<"; by SecurityElement.Escape(record[x]);.
After that when I try to escape it using HttpUtility.JavaScriptStringEncode, which is converted into \u0026lt .
var result = new Dictionary<string, string>();
string[] record = { "<", ">", "John & James" };
for (int x = 0; x < record.Length; x++)
{
string xmlEscaped = SecurityElement.Escape(record[x]);
result.Add($"F{235}_{"Property"}{x + 1}", HttpUtility.JavaScriptStringEncode(xmlEscaped));
}
string json= JsonConvert.SerializeObject(result);
and the result from json is
{"F235_Property1":"\u0026lt;","F235_Property2":"\u0026gt;","F235_Property3":"John \u0026amp; James"}
When I deserialize the same json, I use
var jsonConverted = JsonConvert.DeserializeObject(json);
But after deserialization, the special characters converted are not converting back to original.
Example - \u0026lt is not converting back to "<";
Please help me on this to get resolved .
Thanks in advance.
Deserialize your json to dictionary, and reverse every action you do before serialization for every value in key-value pairs after.
Related
HTTPServletRequest req, has a method getParameterMap() but, the values return a String[] instead of String, for post data as
name=Marry&lastName=John&Age=20.
I see in the post data it's not an array, but getParameterMap() returns array for every key(name or lastName or Age). Any pointers on understanding this in a better way?
The code is available in Approach 2. Approach 1 works completely fine.
Approach 1:
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
String key = (String) parameterNames.nextElement();
String val = req.getParameter(key);
System.out.println("A= <" + key + "> Value<" + val + ">");
}
Approach 2:
Map<String, Object> allMap = req.getParameterMap();
for (String key : allMap.keySet()) {
String[] strArr = (String[]) allMap.get(key);
for (String val : strArr) {
System.out.println("Str Array= " + val);
}
}
If you are expecting pre determined parameters then you can use getParameter(java.lang.String name) method.
Otherwise, approaches given above can be used, but with some differences, in HTTP-request someone can send one or more parameters with the same name.
For example:
name=John, name=Joe, name=Mia
Approach 1 can be used only if you expect client sends only one parameter value for a name, rest of them will be ignored. In this example you can only read "John"
Approach 2 can be used if you expect more than one values with same name. Values will be populated as an array as you showed in the code. Hence you will be able to read all values, i.e "John","Joe","Mia" in this example
Documentation
var clientString = "{\"max\":1214.704958677686}";
JObject o = JObject.Parse(clientString);
var jsonString = o.ToString();
contents of jsonString:
{
"max": 1214.7049586776859
}
this is both in visualizing the object and in doing ToString(). Note that the 686 has mysteriously been expanded to 6859 (precision added). This is a problem for us because the numbers are not exactly the same, and a hash function over the json later does not match.
#Ilija Dimov is correct--JSON.NET parses JSON floats as doubles by default. If you still want to use JObject instead of creating a full blown POCO for deserialization, you can use a JsonTextReader and set the FloatParseHandling option:
var reader = new JsonTextReader(new StringReader(clientString));
reader.FloatParseHandling = FloatParseHandling.Decimal;
JObject obj = JObject.Load(reader);
Console.WriteLine(obj["max"].Value<decimal>()); // 1214.704958677686
The reason your value is changed is because of the nature of floating point numbers in .NET. The JObject.Parse(clientString) method at some point executes the following line:
double d;
double.TryParse("1214.704958677686", NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d);
where d represents the number that you get in the JObject.
As d is of type double and double is floating point number, you didn't get the value you expect. Read more about Binary floating point and .NET.
There is an option in JSON.NET for parsing floating point numbers as decimals and get the precision you need, but to do that you need to create custom class that matches your json string and deserialize the json. Something like this:
public class MyClass
{
[JsonProperty("max")]
public decimal Max { get; set; }
}
var obj = JsonConvert.DeserializeObject<MyClass>(clientString, new JsonSerializerSettings
{
FloatParseHandling = FloatParseHandling.Decimal
});
By using this code sample, the value of max property won't be changed.
You can experiment this behaviour just by parsing to float, double and decimal:
Assert.AreEqual(1214.705f,float.Parse("1214.704958677686"));
Assert.AreEqual(1214.7049586776859, double.Parse("1214.704958677686"));
Assert.AreEqual(1214.704958677686, decimal.Parse("1214.704958677686"));
So json.net is using double as an intermediate type. You can change this by setting FloatParseHandling option.
I am using asp.net. I am trying to split the data which is in datatable. I have a code sample like this:
{ dt=objErrorLoggingDataAccess.GetErrorDetails(errorID);
string[] stringSeparators = new string[] { "Message" };
string error = dt.Rows[0]["Message"].ToString();
string[] test = error.Split(stringSeparators, StringSplitOptions.None);
string PageName = test[0].ToString();
PageNameLabel.Text = PageName;
stringSeparators=new string[] {HttpContext.Current.Request.Url.ToString()};
error = dt.Rows[0]["Message"].ToString();
test = error.Split(stringSeparators, StringSplitOptions.None);
string Message = test[0].ToString();
MessageLabel.Text = Message;}
in the datatable following data is there:
{....ID.......Message.......................................................................................................................
....1........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: naresh#naresh.com
....2........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: iswar#iswar.com}
My problem is: how can I split the Message and store in the label? I want
{http://localhost:10489/images/CategoryIcon/images}
separately and UserName separately and the message separately. How can I do that? By executing the above code I am able to split
{ http://localhost:10489/images/CategoryIcon/images
}
only. How can I split the Message column and store in pageLabel, MessageLabel, UserNamelabel?
I would use a regular expression in this case. Because only by splitting this string looks a little bit to inflexible to me.
I tested your data example against this quick and dirty RegEx:
(?<id>\d+)\.*(?<url>\w+:\/\/[\w#][\w.:#]+\/?[\w\.?=%&=\-#/$,]*)\s*Message\s*:\s*(?<message>.*)UserName:\s*(?<username>([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))
It supports valid URLs and EMail patterns.
Regex regex = new Regex(
"(?<id>\\d+)\\.*(?<url>\\w+:\\/\\/[\\w#][\\w.:#]+\\/?[\\w\\.?"+
"=%&=\\-#/$,]*)\\s*Message\\s*:\\s*(?<message>.*)UserName:\\s"+
"*(?<username>([a-zA-Z0-9_\\-\\.]+)#((\\[[0-9]{1,3}\\.[0-9]{1"+
",3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|"+
"[0-9]{1,3}))",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
// Capture the first Match, if any, in the InputText
Match m = regex.Match(InputText);
// Capture all Matches in the InputText
MatchCollection ms = regex.Matches(InputText);
// Test to see if there is a match in the InputText
bool IsMatch = regex.IsMatch(InputText);
// Get the names of all the named capture groups
// I included your fields as groups: id, url, message and username
string[] GroupNames = regex.GetGroupNames();
I don't know how often you need to call this code. Maybe you get in performance troubles if you have too much data. This regex is q&d - please adjust it to your needs.
I have a hidden field that gets populated with a javascript array of ID's. When I try to iterate the hidden field(called "hidExhibitsIDs") it gives me an error(in the title).
this is my loop:
foreach(string exhibit in hidExhibitsIDs.Value)
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
when I hover over the .value it says it is "string". But when I change the "string exhibit" to "int exhibit" it works, but gives me an internal error(not important right now).
You need to convert string to string array to using in for loop to get strings not characters as your loop suggests. Assuming comma is delimiter character in the hidden field, hidden field value will be converted to string array by split.
foreach(string exhibit in hidExhibitsIDs.Value.Split(','))
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
Value is returning a String. When you do a foreach on a String, it iterates over the individual characters in it. What does the value actually look like? You'll have to parse it correctly before you try to use the data.
Example of what your code is somewhat doing right now:
var myString = "Hey";
foreach (var c in myString)
{
Console.WriteLine(c);
}
Will output:
H
e
y
You can use Char.ToString in order to convert
Link : http://msdn.microsoft.com/en-us/library/3d315df2.aspx
Or you can use this if you want convert your tab of char
char[] tab = new char[] { 'a', 'b', 'c', 'd' };
string str = new string(tab);
Value is a string, which implements IEnumerable<char>, so when you foreach over a string, it loops over each character.
I would run the debugger and see what the actual value of the hidden field is. It can't be an array, since when the POST happens, it is converted into a string.
On the server side, The Value property of a HiddenField (or HtmlInputHidden) is just a string, whose enumerator returns char structs. You'll need to split it to iterate over your IDs.
If you set the value of the hidden field on the client side with a JavaScript array, it will be a comma-separated string on the server side, so something like this will work:
foreach(string exhibit in hidExhibitsIDs.Value.Split(','))
{
comLinkExhibitToTask.Parameters.AddWithValue("#ExhibitID", exhibit);
}
public static string reversewordsInsentence(string sentence)
{
string output = string.Empty;
string word = string.Empty;
foreach(char c in sentence)
{
if (c == ' ')
{
output = word + ' ' + output;
word = string.Empty;
}
else
{
word = word + c;
}
}
output = word + ' ' + output;
return output;
}
I know how to create an array and loop through it normally - but what if I need a multi-column array. e.g. usually I might do something like:
For Each row in NameofArray
Dim name as String = row
Response.Write("Hello " & name & "!")
Next
But what if I want to do something like:
For Each row in NameofArray
Dim name as String = row.name
Dim age as Integer = row.age
Response.Write("Hello " & name & "! You are " & age & " years old!"
Next
If this isn't possible with an array, is there another way I can accomplish this?
Create your custom data type:
public struct DataType
public string Name;
public int Age;
}
Such type you can than use in an array like that:
DataType[] myData = new DataType[100];
myData[0].Name = "myName";
myData[0].Age = 100;
Note, if looping through that array via foreach, the elements returned for each iteration cannot get altered. If this is an requirement for you, consider using 'class' rather than 'struct' in the above DataType declaration. This will come with some other implications though. For example, the instances of a class DataType will explicitely have to be created via the 'new' keyword.
After reading your comment I think my other answer is probably what you are looking for.
What type is row and what type is NameOfArray?
If you would like to make row into a coumpound type with several members then there a several options.
Structure Row
Public Name as String
Public Age as Integer
End Structure
for instance. If you would prefer a reference type substitute Class for Structure.
Or using anonymous types,
Dim row = New With {Name = "Bob", Age = 21}
Then you can use generics to make a list of rows that you can iterate through using ForEach.
Dim NameOfList As System.Collections.Generic.List(of Row)
or if it were a result of a LINQ query somthing that supported
IEnumerable(of New With{Name As String, Age As Int}). //Not sure if this is VB
I'm not certain I uderstand your question and hope this is the kind of thing you were looking for.
As you can see from my fellow answerers, the support for anonymous types is superior in C# but, since you asked the question in VB.Net I will limit myself to that context.
After reading your comment I think I understand the question.
You can do
///Spacer Top
Dim NameOfArray = {New With {.Age = 21, .Name = "Bob"}, New With {.Age = 74, .Name = "Gramps"}}
///Spacer Bottom
If you want to create an IEnumberable anonymous type of Name Age tuples ;-p
Did you tried Dictionary Class. You can loop through the Dictionary using KeyValue pair class.
// Create a new dictionary of strings, with string keys.
//
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
foreach(var item in openWith)
{
Console.WriteLine(item.Key +" can be open with " + item.value);
}
You need to (can) index into your array using the two dimensions ie...
Dim array(,) As Object = { _
{"John",26}, _
{"Mark",4} _
}
For row As Integer = 0 to array.GetUpperBound(0)
Dim name as String = CStr(array(row,0))
Dim age as Integer = CInt(array(row,1))
Response.Write("Hello " & name & "! You are " & age & " years old!")
Next
Though would be better storing this sort of information in a class or user defined type of some kind.